{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "## 配置数据DB"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "38b8b010a9c0efa8"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sqlite\n",
      "['Album', 'Artist', 'Customer', 'Employee', 'Genre', 'Invoice', 'InvoiceLine', 'MediaType', 'Playlist', 'PlaylistTrack', 'Track']\n"
     ]
    },
    {
     "data": {
      "text/plain": "{'table_info': '\\nCREATE TABLE \"Album\" (\\n\\t\"AlbumId\" INTEGER NOT NULL, \\n\\t\"Title\" NVARCHAR(160) NOT NULL, \\n\\t\"ArtistId\" INTEGER NOT NULL, \\n\\tPRIMARY KEY (\"AlbumId\"), \\n\\tFOREIGN KEY(\"ArtistId\") REFERENCES \"Artist\" (\"ArtistId\")\\n)\\n\\n/*\\n3 rows from Album table:\\nAlbumId\\tTitle\\tArtistId\\n1\\tFor Those About To Rock We Salute You\\t1\\n2\\tBalls to the Wall\\t2\\n3\\tRestless and Wild\\t2\\n*/\\n\\n\\nCREATE TABLE \"Artist\" (\\n\\t\"ArtistId\" INTEGER NOT NULL, \\n\\t\"Name\" NVARCHAR(120), \\n\\tPRIMARY KEY (\"ArtistId\")\\n)\\n\\n/*\\n3 rows from Artist table:\\nArtistId\\tName\\n1\\tAC/DC\\n2\\tAccept\\n3\\tAerosmith\\n*/\\n\\n\\nCREATE TABLE \"Customer\" (\\n\\t\"CustomerId\" INTEGER NOT NULL, \\n\\t\"FirstName\" NVARCHAR(40) NOT NULL, \\n\\t\"LastName\" NVARCHAR(20) NOT NULL, \\n\\t\"Company\" NVARCHAR(80), \\n\\t\"Address\" NVARCHAR(70), \\n\\t\"City\" NVARCHAR(40), \\n\\t\"State\" NVARCHAR(40), \\n\\t\"Country\" NVARCHAR(40), \\n\\t\"PostalCode\" NVARCHAR(10), \\n\\t\"Phone\" NVARCHAR(24), \\n\\t\"Fax\" NVARCHAR(24), \\n\\t\"Email\" NVARCHAR(60) NOT NULL, \\n\\t\"SupportRepId\" INTEGER, \\n\\tPRIMARY KEY (\"CustomerId\"), \\n\\tFOREIGN KEY(\"SupportRepId\") REFERENCES \"Employee\" (\"EmployeeId\")\\n)\\n\\n/*\\n3 rows from Customer table:\\nCustomerId\\tFirstName\\tLastName\\tCompany\\tAddress\\tCity\\tState\\tCountry\\tPostalCode\\tPhone\\tFax\\tEmail\\tSupportRepId\\n1\\tLuís\\tGonçalves\\tEmbraer - Empresa Brasileira de Aeronáutica S.A.\\tAv. Brigadeiro Faria Lima, 2170\\tSão José dos Campos\\tSP\\tBrazil\\t12227-000\\t+55 (12) 3923-5555\\t+55 (12) 3923-5566\\tluisg@embraer.com.br\\t3\\n2\\tLeonie\\tKöhler\\tNone\\tTheodor-Heuss-Straße 34\\tStuttgart\\tNone\\tGermany\\t70174\\t+49 0711 2842222\\tNone\\tleonekohler@surfeu.de\\t5\\n3\\tFrançois\\tTremblay\\tNone\\t1498 rue Bélanger\\tMontréal\\tQC\\tCanada\\tH2G 1A7\\t+1 (514) 721-4711\\tNone\\tftremblay@gmail.com\\t3\\n*/\\n\\n\\nCREATE TABLE \"Employee\" (\\n\\t\"EmployeeId\" INTEGER NOT NULL, \\n\\t\"LastName\" NVARCHAR(20) NOT NULL, \\n\\t\"FirstName\" NVARCHAR(20) NOT NULL, \\n\\t\"Title\" NVARCHAR(30), \\n\\t\"ReportsTo\" INTEGER, \\n\\t\"BirthDate\" DATETIME, \\n\\t\"HireDate\" DATETIME, \\n\\t\"Address\" NVARCHAR(70), \\n\\t\"City\" NVARCHAR(40), \\n\\t\"State\" NVARCHAR(40), \\n\\t\"Country\" NVARCHAR(40), \\n\\t\"PostalCode\" NVARCHAR(10), \\n\\t\"Phone\" NVARCHAR(24), \\n\\t\"Fax\" NVARCHAR(24), \\n\\t\"Email\" NVARCHAR(60), \\n\\tPRIMARY KEY (\"EmployeeId\"), \\n\\tFOREIGN KEY(\"ReportsTo\") REFERENCES \"Employee\" (\"EmployeeId\")\\n)\\n\\n/*\\n3 rows from Employee table:\\nEmployeeId\\tLastName\\tFirstName\\tTitle\\tReportsTo\\tBirthDate\\tHireDate\\tAddress\\tCity\\tState\\tCountry\\tPostalCode\\tPhone\\tFax\\tEmail\\n1\\tAdams\\tAndrew\\tGeneral Manager\\tNone\\t1962-02-18 00:00:00\\t2002-08-14 00:00:00\\t11120 Jasper Ave NW\\tEdmonton\\tAB\\tCanada\\tT5K 2N1\\t+1 (780) 428-9482\\t+1 (780) 428-3457\\tandrew@chinookcorp.com\\n2\\tEdwards\\tNancy\\tSales Manager\\t1\\t1958-12-08 00:00:00\\t2002-05-01 00:00:00\\t825 8 Ave SW\\tCalgary\\tAB\\tCanada\\tT2P 2T3\\t+1 (403) 262-3443\\t+1 (403) 262-3322\\tnancy@chinookcorp.com\\n3\\tPeacock\\tJane\\tSales Support Agent\\t2\\t1973-08-29 00:00:00\\t2002-04-01 00:00:00\\t1111 6 Ave SW\\tCalgary\\tAB\\tCanada\\tT2P 5M5\\t+1 (403) 262-3443\\t+1 (403) 262-6712\\tjane@chinookcorp.com\\n*/\\n\\n\\nCREATE TABLE \"Genre\" (\\n\\t\"GenreId\" INTEGER NOT NULL, \\n\\t\"Name\" NVARCHAR(120), \\n\\tPRIMARY KEY (\"GenreId\")\\n)\\n\\n/*\\n3 rows from Genre table:\\nGenreId\\tName\\n1\\tRock\\n2\\tJazz\\n3\\tMetal\\n*/\\n\\n\\nCREATE TABLE \"Invoice\" (\\n\\t\"InvoiceId\" INTEGER NOT NULL, \\n\\t\"CustomerId\" INTEGER NOT NULL, \\n\\t\"InvoiceDate\" DATETIME NOT NULL, \\n\\t\"BillingAddress\" NVARCHAR(70), \\n\\t\"BillingCity\" NVARCHAR(40), \\n\\t\"BillingState\" NVARCHAR(40), \\n\\t\"BillingCountry\" NVARCHAR(40), \\n\\t\"BillingPostalCode\" NVARCHAR(10), \\n\\t\"Total\" NUMERIC(10, 2) NOT NULL, \\n\\tPRIMARY KEY (\"InvoiceId\"), \\n\\tFOREIGN KEY(\"CustomerId\") REFERENCES \"Customer\" (\"CustomerId\")\\n)\\n\\n/*\\n3 rows from Invoice table:\\nInvoiceId\\tCustomerId\\tInvoiceDate\\tBillingAddress\\tBillingCity\\tBillingState\\tBillingCountry\\tBillingPostalCode\\tTotal\\n1\\t2\\t2021-01-01 00:00:00\\tTheodor-Heuss-Straße 34\\tStuttgart\\tNone\\tGermany\\t70174\\t1.98\\n2\\t4\\t2021-01-02 00:00:00\\tUllevålsveien 14\\tOslo\\tNone\\tNorway\\t0171\\t3.96\\n3\\t8\\t2021-01-03 00:00:00\\tGrétrystraat 63\\tBrussels\\tNone\\tBelgium\\t1000\\t5.94\\n*/\\n\\n\\nCREATE TABLE \"InvoiceLine\" (\\n\\t\"InvoiceLineId\" INTEGER NOT NULL, \\n\\t\"InvoiceId\" INTEGER NOT NULL, \\n\\t\"TrackId\" INTEGER NOT NULL, \\n\\t\"UnitPrice\" NUMERIC(10, 2) NOT NULL, \\n\\t\"Quantity\" INTEGER NOT NULL, \\n\\tPRIMARY KEY (\"InvoiceLineId\"), \\n\\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \\n\\tFOREIGN KEY(\"InvoiceId\") REFERENCES \"Invoice\" (\"InvoiceId\")\\n)\\n\\n/*\\n3 rows from InvoiceLine table:\\nInvoiceLineId\\tInvoiceId\\tTrackId\\tUnitPrice\\tQuantity\\n1\\t1\\t2\\t0.99\\t1\\n2\\t1\\t4\\t0.99\\t1\\n3\\t2\\t6\\t0.99\\t1\\n*/\\n\\n\\nCREATE TABLE \"MediaType\" (\\n\\t\"MediaTypeId\" INTEGER NOT NULL, \\n\\t\"Name\" NVARCHAR(120), \\n\\tPRIMARY KEY (\"MediaTypeId\")\\n)\\n\\n/*\\n3 rows from MediaType table:\\nMediaTypeId\\tName\\n1\\tMPEG audio file\\n2\\tProtected AAC audio file\\n3\\tProtected MPEG-4 video file\\n*/\\n\\n\\nCREATE TABLE \"Playlist\" (\\n\\t\"PlaylistId\" INTEGER NOT NULL, \\n\\t\"Name\" NVARCHAR(120), \\n\\tPRIMARY KEY (\"PlaylistId\")\\n)\\n\\n/*\\n3 rows from Playlist table:\\nPlaylistId\\tName\\n1\\tMusic\\n2\\tMovies\\n3\\tTV Shows\\n*/\\n\\n\\nCREATE TABLE \"PlaylistTrack\" (\\n\\t\"PlaylistId\" INTEGER NOT NULL, \\n\\t\"TrackId\" INTEGER NOT NULL, \\n\\tPRIMARY KEY (\"PlaylistId\", \"TrackId\"), \\n\\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \\n\\tFOREIGN KEY(\"PlaylistId\") REFERENCES \"Playlist\" (\"PlaylistId\")\\n)\\n\\n/*\\n3 rows from PlaylistTrack table:\\nPlaylistId\\tTrackId\\n1\\t3402\\n1\\t3389\\n1\\t3390\\n*/\\n\\n\\nCREATE TABLE \"Track\" (\\n\\t\"TrackId\" INTEGER NOT NULL, \\n\\t\"Name\" NVARCHAR(200) NOT NULL, \\n\\t\"AlbumId\" INTEGER, \\n\\t\"MediaTypeId\" INTEGER NOT NULL, \\n\\t\"GenreId\" INTEGER, \\n\\t\"Composer\" NVARCHAR(220), \\n\\t\"Milliseconds\" INTEGER NOT NULL, \\n\\t\"Bytes\" INTEGER, \\n\\t\"UnitPrice\" NUMERIC(10, 2) NOT NULL, \\n\\tPRIMARY KEY (\"TrackId\"), \\n\\tFOREIGN KEY(\"MediaTypeId\") REFERENCES \"MediaType\" (\"MediaTypeId\"), \\n\\tFOREIGN KEY(\"GenreId\") REFERENCES \"Genre\" (\"GenreId\"), \\n\\tFOREIGN KEY(\"AlbumId\") REFERENCES \"Album\" (\"AlbumId\")\\n)\\n\\n/*\\n3 rows from Track table:\\nTrackId\\tName\\tAlbumId\\tMediaTypeId\\tGenreId\\tComposer\\tMilliseconds\\tBytes\\tUnitPrice\\n1\\tFor Those About To Rock (We Salute You)\\t1\\t1\\t1\\tAngus Young, Malcolm Young, Brian Johnson\\t343719\\t11170334\\t0.99\\n2\\tBalls to the Wall\\t2\\t2\\t1\\tU. Dirkschneider, W. Hoffmann, H. Frank, P. Baltes, S. Kaufmann, G. Hoffmann\\t342562\\t5510424\\t0.99\\n3\\tFast As a Shark\\t3\\t2\\t1\\tF. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman\\t230619\\t3990994\\t0.99\\n*/',\n 'table_names': 'Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track'}"
     },
     "execution_count": 409,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.utilities import SQLDatabase\n",
    "\n",
    "db = SQLDatabase.from_uri(\"sqlite:///../../lang_chain/cookbook/Chinook.db\")\n",
    "print(db.dialect)\n",
    "print(db.get_usable_table_names())\n",
    "db.get_context()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:12:21.020823Z",
     "start_time": "2024-11-22T09:12:20.901239Z"
    }
   },
   "id": "44833a54410cface",
   "execution_count": 409
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 工具调用异常代理\n",
    "定义一个函数来来包装ToolNode，以处理错误并将错误消息返回给代理。"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "8f9a11966a3e7571"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "\n",
    "from langchain_core.messages import ToolMessage\n",
    "from typing import Any\n",
    "from langchain_core.runnables import RunnableLambda, RunnableWithFallbacks\n",
    "from langgraph.prebuilt import ToolNode\n",
    "\n",
    "\n",
    "def create_tool_node_with_fallback(tools: list) -> RunnableWithFallbacks[Any, dict]:\n",
    "    \"\"\"\n",
    "    创建一个具有回退功能的ToolNode来处理错误并将其显示给代理。\n",
    "    \"\"\"\n",
    "    return ToolNode(tools).with_fallbacks(\n",
    "        [RunnableLambda(handle_tool_error)], exception_key=\"error\"\n",
    "    )\n",
    "\n",
    "\n",
    "def handle_tool_error(state) -> dict:\n",
    "    error = state.get(\"error\")\n",
    "    tool_calls = state[\"messages\"][-1].tool_calls\n",
    "    return {\n",
    "        \"messages\": [\n",
    "            ToolMessage(\n",
    "                content=f\"Error: {repr(error)}\\n please fix your mistakes.\",\n",
    "                tool_call_id=tc[\"id\"],\n",
    "            )\n",
    "            for tc in tool_calls\n",
    "        ]\n",
    "    }"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:12:21.039305Z",
     "start_time": "2024-11-22T09:12:21.027300Z"
    }
   },
   "id": "b6511b0b14d0d759",
   "execution_count": 410
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 定义工具\n",
    "使用langchain_community包中的`QuerySQLDataBaseTool` `InfoSQLDatabaseTool` `ListSQLDatabaseTool` `QuerySQLCheckerTool`\n",
    "### 获取表名"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "4fd77cfad46bd712"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from typing import List\n",
    "\n",
    "from langchain_community.tools import ListSQLDatabaseTool, InfoSQLDatabaseTool, QuerySQLDataBaseTool\n",
    "from langchain_community.utilities import SQLDatabase\n",
    "from langchain_core.tools import BaseToolkit, BaseTool\n",
    "from pydantic import Field, ConfigDict\n",
    "\n",
    "\n",
    "class SQLDatabaseJFToolkit(BaseToolkit):\n",
    "    \"\"\"SQL Database Toolkit\"\"\"\n",
    "    db: SQLDatabase = Field(exclude=True)\n",
    "    model_config = ConfigDict(\n",
    "        arbitrary_types_allowed=True,\n",
    "    )\n",
    "\n",
    "    @property\n",
    "    def dialect(self) -> str:\n",
    "        \"\"\"Return string representation of SQL dialect to use.\"\"\"\n",
    "        return self.db.dialect\n",
    "\n",
    "    def get_tools(self) -> List[BaseTool]:\n",
    "        \"\"\"Get the tools in the toolkit.\"\"\"\n",
    "        list_sql_database_tool = ListSQLDatabaseTool(db=self.db)\n",
    "        # info_sql_database_tool_description = (\n",
    "        #     \"Input to this tool is a comma-separated list of tables, output is the \"\n",
    "        #     \"schema and sample rows for those tables. \"\n",
    "        #     \"Be sure that the tables actually exist by calling \"\n",
    "        #     f\"{list_sql_database_tool.name} first! \"\n",
    "        #     \"Example Input: table1, table2, table3\"\n",
    "        # )\n",
    "        info_sql_database_tool = InfoSQLDatabaseTool(\n",
    "            db=self.db,\n",
    "        )\n",
    "        # query_sql_database_tool_description = (\n",
    "        #     \"Input to this tool is a detailed and correct SQL query, output is a \"\n",
    "        #     \"result from the database. If the query is not correct, an error message \"\n",
    "        #     \"will be returned. If an error is returned, rewrite the query, check the \"\n",
    "        #     \"query, and try again. If you encounter an issue with Unknown column \"\n",
    "        #     f\"'xxxx' in 'field list', use {info_sql_database_tool.name} \"\n",
    "        #     \"to query the correct table fields.\"\n",
    "        # )\n",
    "        query_sql_database_tool = QuerySQLDataBaseTool(\n",
    "            db=self.db,\n",
    "        )\n",
    "\n",
    "        return [\n",
    "            query_sql_database_tool,\n",
    "            info_sql_database_tool,\n",
    "            list_sql_database_tool,\n",
    "        ]\n",
    "\n",
    "    def get_context(self) -> dict:\n",
    "        \"\"\"Return db context that you may want in agent prompt.\"\"\"\n",
    "        return self.db.get_context()\n",
    "\n",
    "\n",
    "sql_db_toolkit = SQLDatabaseJFToolkit(db=db)\n",
    "# list_tables_tool = ListSQLDatabaseTool(db=db)\n",
    "# list_tables_tool.invoke(\"Customer\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:12:21.064999Z",
     "start_time": "2024-11-22T09:12:21.043091Z"
    }
   },
   "id": "f69658d9076fa9e",
   "execution_count": 411
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 获取表结构\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "f30093c456c9985b"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "'\\nCREATE TABLE \"Album\" (\\n\\t\"AlbumId\" INTEGER NOT NULL, \\n\\t\"Title\" NVARCHAR(160) NOT NULL, \\n\\t\"ArtistId\" INTEGER NOT NULL, \\n\\tPRIMARY KEY (\"AlbumId\"), \\n\\tFOREIGN KEY(\"ArtistId\") REFERENCES \"Artist\" (\"ArtistId\")\\n)\\n\\n/*\\n3 rows from Album table:\\nAlbumId\\tTitle\\tArtistId\\n1\\tFor Those About To Rock We Salute You\\t1\\n2\\tBalls to the Wall\\t2\\n3\\tRestless and Wild\\t2\\n*/\\n\\n\\nCREATE TABLE \"Customer\" (\\n\\t\"CustomerId\" INTEGER NOT NULL, \\n\\t\"FirstName\" NVARCHAR(40) NOT NULL, \\n\\t\"LastName\" NVARCHAR(20) NOT NULL, \\n\\t\"Company\" NVARCHAR(80), \\n\\t\"Address\" NVARCHAR(70), \\n\\t\"City\" NVARCHAR(40), \\n\\t\"State\" NVARCHAR(40), \\n\\t\"Country\" NVARCHAR(40), \\n\\t\"PostalCode\" NVARCHAR(10), \\n\\t\"Phone\" NVARCHAR(24), \\n\\t\"Fax\" NVARCHAR(24), \\n\\t\"Email\" NVARCHAR(60) NOT NULL, \\n\\t\"SupportRepId\" INTEGER, \\n\\tPRIMARY KEY (\"CustomerId\"), \\n\\tFOREIGN KEY(\"SupportRepId\") REFERENCES \"Employee\" (\"EmployeeId\")\\n)\\n\\n/*\\n3 rows from Customer table:\\nCustomerId\\tFirstName\\tLastName\\tCompany\\tAddress\\tCity\\tState\\tCountry\\tPostalCode\\tPhone\\tFax\\tEmail\\tSupportRepId\\n1\\tLuís\\tGonçalves\\tEmbraer - Empresa Brasileira de Aeronáutica S.A.\\tAv. Brigadeiro Faria Lima, 2170\\tSão José dos Campos\\tSP\\tBrazil\\t12227-000\\t+55 (12) 3923-5555\\t+55 (12) 3923-5566\\tluisg@embraer.com.br\\t3\\n2\\tLeonie\\tKöhler\\tNone\\tTheodor-Heuss-Straße 34\\tStuttgart\\tNone\\tGermany\\t70174\\t+49 0711 2842222\\tNone\\tleonekohler@surfeu.de\\t5\\n3\\tFrançois\\tTremblay\\tNone\\t1498 rue Bélanger\\tMontréal\\tQC\\tCanada\\tH2G 1A7\\t+1 (514) 721-4711\\tNone\\tftremblay@gmail.com\\t3\\n*/\\n\\n\\nCREATE TABLE \"Invoice\" (\\n\\t\"InvoiceId\" INTEGER NOT NULL, \\n\\t\"CustomerId\" INTEGER NOT NULL, \\n\\t\"InvoiceDate\" DATETIME NOT NULL, \\n\\t\"BillingAddress\" NVARCHAR(70), \\n\\t\"BillingCity\" NVARCHAR(40), \\n\\t\"BillingState\" NVARCHAR(40), \\n\\t\"BillingCountry\" NVARCHAR(40), \\n\\t\"BillingPostalCode\" NVARCHAR(10), \\n\\t\"Total\" NUMERIC(10, 2) NOT NULL, \\n\\tPRIMARY KEY (\"InvoiceId\"), \\n\\tFOREIGN KEY(\"CustomerId\") REFERENCES \"Customer\" (\"CustomerId\")\\n)\\n\\n/*\\n3 rows from Invoice table:\\nInvoiceId\\tCustomerId\\tInvoiceDate\\tBillingAddress\\tBillingCity\\tBillingState\\tBillingCountry\\tBillingPostalCode\\tTotal\\n1\\t2\\t2021-01-01 00:00:00\\tTheodor-Heuss-Straße 34\\tStuttgart\\tNone\\tGermany\\t70174\\t1.98\\n2\\t4\\t2021-01-02 00:00:00\\tUllevålsveien 14\\tOslo\\tNone\\tNorway\\t0171\\t3.96\\n3\\t8\\t2021-01-03 00:00:00\\tGrétrystraat 63\\tBrussels\\tNone\\tBelgium\\t1000\\t5.94\\n*/'"
     },
     "execution_count": 412,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.tools import InfoSQLDatabaseTool\n",
    "\n",
    "get_schema_tool = next(tool for tool in sql_db_toolkit.get_tools() if tool.name == \"sql_db_schema\")\n",
    "get_schema_tool.invoke(\"Album,Customer,Invoice\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:12:21.092039Z",
     "start_time": "2024-11-22T09:12:21.072011Z"
    }
   },
   "id": "67de84dc801e7fbb",
   "execution_count": 412
  },
  {
   "cell_type": "markdown",
   "source": [
    "### sql checker"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "cb2803a7e4f13c21"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "True"
     },
     "execution_count": 413,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.chat_models import ChatTongyi\n",
    "from pydantic import BaseModel\n",
    "from pydantic import Field\n",
    "from langchain_core.messages import AIMessage\n",
    "import os\n",
    "from dotenv import load_dotenv\n",
    "from langchain_community.tools import QuerySQLCheckerTool\n",
    "from typing import Annotated, Literal\n",
    "\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "from typing_extensions import TypedDict\n",
    "\n",
    "from langgraph.graph.message import AnyMessage, add_messages\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "\n",
    "class State(TypedDict):\n",
    "    messages: Annotated[list[AnyMessage], add_messages]\n",
    "\n",
    "\n",
    "load_dotenv()\n",
    "# \n",
    "# class SubmitFinalAnswer(BaseModel):\n",
    "#     \"\"\"根据查询结果向用户提交最终答案。\"\"\"\n",
    "# \n",
    "#     final_answer: str = Field(..., description=\"用户的最终答案\")\n",
    "# \n",
    "# class QueryEffective(BaseModel):\n",
    "#         \"\"\"有效的查询语句.\"\"\"\n",
    "#         sql_effective: str = Field(description=\"有效查询语句 'yes' or 'no'\")\n",
    "#         sql:str = Field(description=\"查询语句\")\n",
    "#         error:str = Field(description=\"错误信息\")\n",
    "#         # sql:str = Field(description=\"有效查询语句\")\n",
    "#         \n",
    "# def query_check_node(state: State, config) -> dict[str, list[AIMessage]]:\n",
    "#     \"\"\"使用此工具在执行查询之前仔细检查查询是否正确。\"\"\"\n",
    "#     # query_check = QuerySQLCheckerTool(db=db, llm=ChatOpenAI(\n",
    "#     #     # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\n",
    "#     #     openai_api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\n",
    "#     #     openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "#     #     model_name=\"qwen-max\",\n",
    "#     #     verbose=True, temperature=0\n",
    "#     # ))\n",
    "#     dialect = db.dialect\n",
    "#     query_check_system = f\"\"\"你是一个注重细节的SQL专家.\n",
    "#     请仔细检查{dialect}查询中的常见错误，包括:\n",
    "#     - 在包含NULL值的情况下使用NOT IN\n",
    "#     - 本应使用UNION ALL却错误地使用了UNION\n",
    "#     - 使用BETWEEN表示非闭区间范围\n",
    "#     - 谓词中数据类型不匹配\n",
    "#     - 未正确引用标识符\n",
    "#     - 未转换为正确的数据类型\n",
    "#     - 用于连接的列不正确\n",
    "#     - 函数参数数量不正确\n",
    "#     \n",
    "#     如果没有错误返回:yes，否则返回:no。\n",
    "#     \"\"\"\n",
    "#     # 如果存在上述任何错误，请重写查询且累计重写次数不超过2次，重写后再重新检查查询中的常见错误。\n",
    "# \n",
    "#     query_check_prompt = ChatPromptTemplate.from_messages(\n",
    "#         [(\"system\", query_check_system), (\"placeholder\", \"{messages}\")]\n",
    "#     )\n",
    "#     check_llm = ChatTongyi(\n",
    "#         # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\n",
    "#         api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\n",
    "#         # openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "#         model=\"qwen-max\",\n",
    "#         verbose=True, temperature=0\n",
    "#     )\n",
    "#     \n",
    "#     query_check = query_check_prompt | check_llm.with_structured_output(QueryEffective)\n",
    "#     message = query_check.invoke({\"messages\": [state[\"messages\"][-1]]})\n",
    "#     return {\"messages\": [message]}\n",
    "# \n",
    "# \n",
    "# result = query_check_node({\"messages\": [AIMessage(content=\"select * from Customers  limit 2\")]}, None)\n",
    "# result"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:12:21.131627Z",
     "start_time": "2024-11-22T09:12:21.107484Z"
    }
   },
   "id": "914d377726d2960c",
   "execution_count": 413
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 执行SQL查询"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "76d5ab5d6613f644"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "\"[(1, 'Luís', 'Gonçalves', 'Embraer - Empresa Brasileira de Aeronáutica S.A.', 'Av. Brigadeiro Faria Lima, 2170', 'São José dos Campos', 'SP', 'Brazil', '12227-000', '+55 (12) 3923-5555', '+55 (12) 3923-5566', 'luisg@embraer.com.br', 3), (2, 'Leonie', 'Köhler', None, 'Theodor-Heuss-Straße 34', 'Stuttgart', None, 'Germany', '70174', '+49 0711 2842222', None, 'leonekohler@surfeu.de', 5)]\""
     },
     "execution_count": 414,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.tools import QuerySQLDataBaseTool\n",
    "\n",
    "sql_db_query_tool = next(tool for tool in sql_db_toolkit.get_tools() if tool.name == \"sql_db_query\")\n",
    "result = sql_db_query_tool.invoke(\"select * from Customer limit 2\")\n",
    "result\n",
    "# sql_db_query_tool.name"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:12:21.255201Z",
     "start_time": "2024-11-22T09:12:21.242582Z"
    }
   },
   "id": "63f68dd075591614",
   "execution_count": 414
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   },
   "id": "e078da06b7cdc403"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## workflow"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "3aa28fe9bdefbe9c"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "ename": "APIConnectionError",
     "evalue": "Connection error.",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mConnectError\u001B[0m                              Traceback (most recent call last)",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:72\u001B[0m, in \u001B[0;36mmap_httpcore_exceptions\u001B[0;34m()\u001B[0m\n\u001B[1;32m     71\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m---> 72\u001B[0m     \u001B[38;5;28;01myield\u001B[39;00m\n\u001B[1;32m     73\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:236\u001B[0m, in \u001B[0;36mHTTPTransport.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    235\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m map_httpcore_exceptions():\n\u001B[0;32m--> 236\u001B[0m     resp \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_pool\u001B[38;5;241m.\u001B[39mhandle_request(req)\n\u001B[1;32m    238\u001B[0m \u001B[38;5;28;01massert\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(resp\u001B[38;5;241m.\u001B[39mstream, typing\u001B[38;5;241m.\u001B[39mIterable)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:216\u001B[0m, in \u001B[0;36mConnectionPool.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    215\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_close_connections(closing)\n\u001B[0;32m--> 216\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m exc \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m    218\u001B[0m \u001B[38;5;66;03m# Return the response. Note that in this case we still have to manage\u001B[39;00m\n\u001B[1;32m    219\u001B[0m \u001B[38;5;66;03m# the point at which the response is closed.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:196\u001B[0m, in \u001B[0;36mConnectionPool.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    194\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m    195\u001B[0m     \u001B[38;5;66;03m# Send the request on the assigned connection.\u001B[39;00m\n\u001B[0;32m--> 196\u001B[0m     response \u001B[38;5;241m=\u001B[39m connection\u001B[38;5;241m.\u001B[39mhandle_request(\n\u001B[1;32m    197\u001B[0m         pool_request\u001B[38;5;241m.\u001B[39mrequest\n\u001B[1;32m    198\u001B[0m     )\n\u001B[1;32m    199\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m ConnectionNotAvailable:\n\u001B[1;32m    200\u001B[0m     \u001B[38;5;66;03m# In some cases a connection may initially be available to\u001B[39;00m\n\u001B[1;32m    201\u001B[0m     \u001B[38;5;66;03m# handle a request, but then become unavailable.\u001B[39;00m\n\u001B[1;32m    202\u001B[0m     \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[1;32m    203\u001B[0m     \u001B[38;5;66;03m# In this case we clear the connection and try again.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection.py:99\u001B[0m, in \u001B[0;36mHTTPConnection.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m     98\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connect_failed \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mTrue\u001B[39;00m\n\u001B[0;32m---> 99\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m exc\n\u001B[1;32m    101\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connection\u001B[38;5;241m.\u001B[39mhandle_request(request)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection.py:76\u001B[0m, in \u001B[0;36mHTTPConnection.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m     75\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connection \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[0;32m---> 76\u001B[0m     stream \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connect(request)\n\u001B[1;32m     78\u001B[0m     ssl_object \u001B[38;5;241m=\u001B[39m stream\u001B[38;5;241m.\u001B[39mget_extra_info(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mssl_object\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection.py:122\u001B[0m, in \u001B[0;36mHTTPConnection._connect\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    121\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m Trace(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mconnect_tcp\u001B[39m\u001B[38;5;124m\"\u001B[39m, logger, request, kwargs) \u001B[38;5;28;01mas\u001B[39;00m trace:\n\u001B[0;32m--> 122\u001B[0m     stream \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_network_backend\u001B[38;5;241m.\u001B[39mconnect_tcp(\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    123\u001B[0m     trace\u001B[38;5;241m.\u001B[39mreturn_value \u001B[38;5;241m=\u001B[39m stream\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_backends/sync.py:205\u001B[0m, in \u001B[0;36mSyncBackend.connect_tcp\u001B[0;34m(self, host, port, timeout, local_address, socket_options)\u001B[0m\n\u001B[1;32m    200\u001B[0m exc_map: ExceptionMapping \u001B[38;5;241m=\u001B[39m {\n\u001B[1;32m    201\u001B[0m     socket\u001B[38;5;241m.\u001B[39mtimeout: ConnectTimeout,\n\u001B[1;32m    202\u001B[0m     \u001B[38;5;167;01mOSError\u001B[39;00m: ConnectError,\n\u001B[1;32m    203\u001B[0m }\n\u001B[0;32m--> 205\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m map_exceptions(exc_map):\n\u001B[1;32m    206\u001B[0m     sock \u001B[38;5;241m=\u001B[39m socket\u001B[38;5;241m.\u001B[39mcreate_connection(\n\u001B[1;32m    207\u001B[0m         address,\n\u001B[1;32m    208\u001B[0m         timeout,\n\u001B[1;32m    209\u001B[0m         source_address\u001B[38;5;241m=\u001B[39msource_address,\n\u001B[1;32m    210\u001B[0m     )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/contextlib.py:158\u001B[0m, in \u001B[0;36m_GeneratorContextManager.__exit__\u001B[0;34m(self, typ, value, traceback)\u001B[0m\n\u001B[1;32m    157\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 158\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgen\u001B[38;5;241m.\u001B[39mthrow(value)\n\u001B[1;32m    159\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mStopIteration\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n\u001B[1;32m    160\u001B[0m     \u001B[38;5;66;03m# Suppress StopIteration *unless* it's the same exception that\u001B[39;00m\n\u001B[1;32m    161\u001B[0m     \u001B[38;5;66;03m# was passed to throw().  This prevents a StopIteration\u001B[39;00m\n\u001B[1;32m    162\u001B[0m     \u001B[38;5;66;03m# raised inside the \"with\" statement from being suppressed.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_exceptions.py:14\u001B[0m, in \u001B[0;36mmap_exceptions\u001B[0;34m(map)\u001B[0m\n\u001B[1;32m     13\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(exc, from_exc):\n\u001B[0;32m---> 14\u001B[0m         \u001B[38;5;28;01mraise\u001B[39;00m to_exc(exc) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mexc\u001B[39;00m\n\u001B[1;32m     15\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m\n",
      "\u001B[0;31mConnectError\u001B[0m: [Errno 61] Connection refused",
      "\nThe above exception was the direct cause of the following exception:\n",
      "\u001B[0;31mConnectError\u001B[0m                              Traceback (most recent call last)",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:990\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m    989\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 990\u001B[0m     response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_client\u001B[38;5;241m.\u001B[39msend(\n\u001B[1;32m    991\u001B[0m         request,\n\u001B[1;32m    992\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_should_stream_response_body(request\u001B[38;5;241m=\u001B[39mrequest),\n\u001B[1;32m    993\u001B[0m         \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m    994\u001B[0m     )\n\u001B[1;32m    995\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m httpx\u001B[38;5;241m.\u001B[39mTimeoutException \u001B[38;5;28;01mas\u001B[39;00m err:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:926\u001B[0m, in \u001B[0;36mClient.send\u001B[0;34m(self, request, stream, auth, follow_redirects)\u001B[0m\n\u001B[1;32m    924\u001B[0m auth \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_build_request_auth(request, auth)\n\u001B[0;32m--> 926\u001B[0m response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_send_handling_auth(\n\u001B[1;32m    927\u001B[0m     request,\n\u001B[1;32m    928\u001B[0m     auth\u001B[38;5;241m=\u001B[39mauth,\n\u001B[1;32m    929\u001B[0m     follow_redirects\u001B[38;5;241m=\u001B[39mfollow_redirects,\n\u001B[1;32m    930\u001B[0m     history\u001B[38;5;241m=\u001B[39m[],\n\u001B[1;32m    931\u001B[0m )\n\u001B[1;32m    932\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:954\u001B[0m, in \u001B[0;36mClient._send_handling_auth\u001B[0;34m(self, request, auth, follow_redirects, history)\u001B[0m\n\u001B[1;32m    953\u001B[0m \u001B[38;5;28;01mwhile\u001B[39;00m \u001B[38;5;28;01mTrue\u001B[39;00m:\n\u001B[0;32m--> 954\u001B[0m     response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_send_handling_redirects(\n\u001B[1;32m    955\u001B[0m         request,\n\u001B[1;32m    956\u001B[0m         follow_redirects\u001B[38;5;241m=\u001B[39mfollow_redirects,\n\u001B[1;32m    957\u001B[0m         history\u001B[38;5;241m=\u001B[39mhistory,\n\u001B[1;32m    958\u001B[0m     )\n\u001B[1;32m    959\u001B[0m     \u001B[38;5;28;01mtry\u001B[39;00m:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:991\u001B[0m, in \u001B[0;36mClient._send_handling_redirects\u001B[0;34m(self, request, follow_redirects, history)\u001B[0m\n\u001B[1;32m    989\u001B[0m     hook(request)\n\u001B[0;32m--> 991\u001B[0m response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_send_single_request(request)\n\u001B[1;32m    992\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:1027\u001B[0m, in \u001B[0;36mClient._send_single_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m   1026\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m request_context(request\u001B[38;5;241m=\u001B[39mrequest):\n\u001B[0;32m-> 1027\u001B[0m     response \u001B[38;5;241m=\u001B[39m transport\u001B[38;5;241m.\u001B[39mhandle_request(request)\n\u001B[1;32m   1029\u001B[0m \u001B[38;5;28;01massert\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(response\u001B[38;5;241m.\u001B[39mstream, SyncByteStream)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:235\u001B[0m, in \u001B[0;36mHTTPTransport.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    223\u001B[0m req \u001B[38;5;241m=\u001B[39m httpcore\u001B[38;5;241m.\u001B[39mRequest(\n\u001B[1;32m    224\u001B[0m     method\u001B[38;5;241m=\u001B[39mrequest\u001B[38;5;241m.\u001B[39mmethod,\n\u001B[1;32m    225\u001B[0m     url\u001B[38;5;241m=\u001B[39mhttpcore\u001B[38;5;241m.\u001B[39mURL(\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    233\u001B[0m     extensions\u001B[38;5;241m=\u001B[39mrequest\u001B[38;5;241m.\u001B[39mextensions,\n\u001B[1;32m    234\u001B[0m )\n\u001B[0;32m--> 235\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m map_httpcore_exceptions():\n\u001B[1;32m    236\u001B[0m     resp \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_pool\u001B[38;5;241m.\u001B[39mhandle_request(req)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/contextlib.py:158\u001B[0m, in \u001B[0;36m_GeneratorContextManager.__exit__\u001B[0;34m(self, typ, value, traceback)\u001B[0m\n\u001B[1;32m    157\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 158\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgen\u001B[38;5;241m.\u001B[39mthrow(value)\n\u001B[1;32m    159\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mStopIteration\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n\u001B[1;32m    160\u001B[0m     \u001B[38;5;66;03m# Suppress StopIteration *unless* it's the same exception that\u001B[39;00m\n\u001B[1;32m    161\u001B[0m     \u001B[38;5;66;03m# was passed to throw().  This prevents a StopIteration\u001B[39;00m\n\u001B[1;32m    162\u001B[0m     \u001B[38;5;66;03m# raised inside the \"with\" statement from being suppressed.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:89\u001B[0m, in \u001B[0;36mmap_httpcore_exceptions\u001B[0;34m()\u001B[0m\n\u001B[1;32m     88\u001B[0m message \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mstr\u001B[39m(exc)\n\u001B[0;32m---> 89\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m mapped_exc(message) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mexc\u001B[39;00m\n",
      "\u001B[0;31mConnectError\u001B[0m: [Errno 61] Connection refused",
      "\nThe above exception was the direct cause of the following exception:\n",
      "\u001B[0;31mAPIConnectionError\u001B[0m                        Traceback (most recent call last)",
      "Cell \u001B[0;32mIn[415], line 83\u001B[0m\n\u001B[1;32m     79\u001B[0m     message \u001B[38;5;241m=\u001B[39m llm\u001B[38;5;241m.\u001B[39minvoke(state)\n\u001B[1;32m     81\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [message] }\n\u001B[0;32m---> 83\u001B[0m query_generate_node({\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124muser\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m我需要2人生日是1970年之前的老干部\u001B[39m\u001B[38;5;124m\"\u001B[39m)]}, \u001B[38;5;28;01mNone\u001B[39;00m)\n",
      "Cell \u001B[0;32mIn[415], line 79\u001B[0m, in \u001B[0;36mquery_generate_node\u001B[0;34m(state, config)\u001B[0m\n\u001B[1;32m     63\u001B[0m \u001B[38;5;66;03m# llm = query_generate_prompt | ChatOpenAI(\u001B[39;00m\n\u001B[1;32m     64\u001B[0m \u001B[38;5;66;03m#     # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\u001B[39;00m\n\u001B[1;32m     65\u001B[0m \u001B[38;5;66;03m#     openai_api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\u001B[39;00m\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m     68\u001B[0m \u001B[38;5;66;03m#     verbose=True, temperature=0\u001B[39;00m\n\u001B[1;32m     69\u001B[0m \u001B[38;5;66;03m# ).bind_tools([sql_db_query_tool])\u001B[39;00m\n\u001B[1;32m     70\u001B[0m llm \u001B[38;5;241m=\u001B[39m query_generate_prompt \u001B[38;5;241m|\u001B[39m ChatOpenAI(\n\u001B[1;32m     71\u001B[0m     \u001B[38;5;66;03m# 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\u001B[39;00m\n\u001B[1;32m     72\u001B[0m     api_key\u001B[38;5;241m=\u001B[39mos\u001B[38;5;241m.\u001B[39mgetenv(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mDASHSCOPE_API_KEY\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m     76\u001B[0m     verbose\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m, temperature\u001B[38;5;241m=\u001B[39m\u001B[38;5;241m0.5\u001B[39m\n\u001B[1;32m     77\u001B[0m )\u001B[38;5;241m.\u001B[39mbind_tools([sql_db_query_tool])\n\u001B[0;32m---> 79\u001B[0m message \u001B[38;5;241m=\u001B[39m llm\u001B[38;5;241m.\u001B[39minvoke(state)\n\u001B[1;32m     81\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [message] }\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/runnables/base.py:3024\u001B[0m, in \u001B[0;36mRunnableSequence.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m   3022\u001B[0m             \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m   3023\u001B[0m         \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m-> 3024\u001B[0m             \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config)\n\u001B[1;32m   3025\u001B[0m \u001B[38;5;66;03m# finish the root run\u001B[39;00m\n\u001B[1;32m   3026\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mBaseException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m e:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/runnables/base.py:5354\u001B[0m, in \u001B[0;36mRunnableBindingBase.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m   5348\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21minvoke\u001B[39m(\n\u001B[1;32m   5349\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m   5350\u001B[0m     \u001B[38;5;28minput\u001B[39m: Input,\n\u001B[1;32m   5351\u001B[0m     config: Optional[RunnableConfig] \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   5352\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Optional[Any],\n\u001B[1;32m   5353\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m Output:\n\u001B[0;32m-> 5354\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mbound\u001B[38;5;241m.\u001B[39minvoke(\n\u001B[1;32m   5355\u001B[0m         \u001B[38;5;28minput\u001B[39m,\n\u001B[1;32m   5356\u001B[0m         \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_merge_configs(config),\n\u001B[1;32m   5357\u001B[0m         \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39m{\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mkwargs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs},\n\u001B[1;32m   5358\u001B[0m     )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:286\u001B[0m, in \u001B[0;36mBaseChatModel.invoke\u001B[0;34m(self, input, config, stop, **kwargs)\u001B[0m\n\u001B[1;32m    275\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21minvoke\u001B[39m(\n\u001B[1;32m    276\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m    277\u001B[0m     \u001B[38;5;28minput\u001B[39m: LanguageModelInput,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    281\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Any,\n\u001B[1;32m    282\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m BaseMessage:\n\u001B[1;32m    283\u001B[0m     config \u001B[38;5;241m=\u001B[39m ensure_config(config)\n\u001B[1;32m    284\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m cast(\n\u001B[1;32m    285\u001B[0m         ChatGeneration,\n\u001B[0;32m--> 286\u001B[0m         \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgenerate_prompt(\n\u001B[1;32m    287\u001B[0m             [\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_convert_input(\u001B[38;5;28minput\u001B[39m)],\n\u001B[1;32m    288\u001B[0m             stop\u001B[38;5;241m=\u001B[39mstop,\n\u001B[1;32m    289\u001B[0m             callbacks\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcallbacks\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    290\u001B[0m             tags\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtags\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    291\u001B[0m             metadata\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmetadata\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    292\u001B[0m             run_name\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrun_name\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    293\u001B[0m             run_id\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mpop(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrun_id\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;28;01mNone\u001B[39;00m),\n\u001B[1;32m    294\u001B[0m             \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m    295\u001B[0m         )\u001B[38;5;241m.\u001B[39mgenerations[\u001B[38;5;241m0\u001B[39m][\u001B[38;5;241m0\u001B[39m],\n\u001B[1;32m    296\u001B[0m     )\u001B[38;5;241m.\u001B[39mmessage\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:786\u001B[0m, in \u001B[0;36mBaseChatModel.generate_prompt\u001B[0;34m(self, prompts, stop, callbacks, **kwargs)\u001B[0m\n\u001B[1;32m    778\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mgenerate_prompt\u001B[39m(\n\u001B[1;32m    779\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m    780\u001B[0m     prompts: \u001B[38;5;28mlist\u001B[39m[PromptValue],\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    783\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Any,\n\u001B[1;32m    784\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m LLMResult:\n\u001B[1;32m    785\u001B[0m     prompt_messages \u001B[38;5;241m=\u001B[39m [p\u001B[38;5;241m.\u001B[39mto_messages() \u001B[38;5;28;01mfor\u001B[39;00m p \u001B[38;5;129;01min\u001B[39;00m prompts]\n\u001B[0;32m--> 786\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgenerate(prompt_messages, stop\u001B[38;5;241m=\u001B[39mstop, callbacks\u001B[38;5;241m=\u001B[39mcallbacks, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:643\u001B[0m, in \u001B[0;36mBaseChatModel.generate\u001B[0;34m(self, messages, stop, callbacks, tags, metadata, run_name, run_id, **kwargs)\u001B[0m\n\u001B[1;32m    641\u001B[0m         \u001B[38;5;28;01mif\u001B[39;00m run_managers:\n\u001B[1;32m    642\u001B[0m             run_managers[i]\u001B[38;5;241m.\u001B[39mon_llm_error(e, response\u001B[38;5;241m=\u001B[39mLLMResult(generations\u001B[38;5;241m=\u001B[39m[]))\n\u001B[0;32m--> 643\u001B[0m         \u001B[38;5;28;01mraise\u001B[39;00m e\n\u001B[1;32m    644\u001B[0m flattened_outputs \u001B[38;5;241m=\u001B[39m [\n\u001B[1;32m    645\u001B[0m     LLMResult(generations\u001B[38;5;241m=\u001B[39m[res\u001B[38;5;241m.\u001B[39mgenerations], llm_output\u001B[38;5;241m=\u001B[39mres\u001B[38;5;241m.\u001B[39mllm_output)  \u001B[38;5;66;03m# type: ignore[list-item]\u001B[39;00m\n\u001B[1;32m    646\u001B[0m     \u001B[38;5;28;01mfor\u001B[39;00m res \u001B[38;5;129;01min\u001B[39;00m results\n\u001B[1;32m    647\u001B[0m ]\n\u001B[1;32m    648\u001B[0m llm_output \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_combine_llm_outputs([res\u001B[38;5;241m.\u001B[39mllm_output \u001B[38;5;28;01mfor\u001B[39;00m res \u001B[38;5;129;01min\u001B[39;00m results])\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:633\u001B[0m, in \u001B[0;36mBaseChatModel.generate\u001B[0;34m(self, messages, stop, callbacks, tags, metadata, run_name, run_id, **kwargs)\u001B[0m\n\u001B[1;32m    630\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m i, m \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28menumerate\u001B[39m(messages):\n\u001B[1;32m    631\u001B[0m     \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m    632\u001B[0m         results\u001B[38;5;241m.\u001B[39mappend(\n\u001B[0;32m--> 633\u001B[0m             \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate_with_cache(\n\u001B[1;32m    634\u001B[0m                 m,\n\u001B[1;32m    635\u001B[0m                 stop\u001B[38;5;241m=\u001B[39mstop,\n\u001B[1;32m    636\u001B[0m                 run_manager\u001B[38;5;241m=\u001B[39mrun_managers[i] \u001B[38;5;28;01mif\u001B[39;00m run_managers \u001B[38;5;28;01melse\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m    637\u001B[0m                 \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m    638\u001B[0m             )\n\u001B[1;32m    639\u001B[0m         )\n\u001B[1;32m    640\u001B[0m     \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mBaseException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[1;32m    641\u001B[0m         \u001B[38;5;28;01mif\u001B[39;00m run_managers:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:851\u001B[0m, in \u001B[0;36mBaseChatModel._generate_with_cache\u001B[0;34m(self, messages, stop, run_manager, **kwargs)\u001B[0m\n\u001B[1;32m    849\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    850\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m inspect\u001B[38;5;241m.\u001B[39msignature(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate)\u001B[38;5;241m.\u001B[39mparameters\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrun_manager\u001B[39m\u001B[38;5;124m\"\u001B[39m):\n\u001B[0;32m--> 851\u001B[0m         result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate(\n\u001B[1;32m    852\u001B[0m             messages, stop\u001B[38;5;241m=\u001B[39mstop, run_manager\u001B[38;5;241m=\u001B[39mrun_manager, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs\n\u001B[1;32m    853\u001B[0m         )\n\u001B[1;32m    854\u001B[0m     \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    855\u001B[0m         result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate(messages, stop\u001B[38;5;241m=\u001B[39mstop, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_openai/chat_models/base.py:705\u001B[0m, in \u001B[0;36mBaseChatOpenAI._generate\u001B[0;34m(self, messages, stop, run_manager, **kwargs)\u001B[0m\n\u001B[1;32m    703\u001B[0m     generation_info \u001B[38;5;241m=\u001B[39m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mheaders\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mdict\u001B[39m(raw_response\u001B[38;5;241m.\u001B[39mheaders)}\n\u001B[1;32m    704\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m--> 705\u001B[0m     response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mclient\u001B[38;5;241m.\u001B[39mcreate(\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mpayload)\n\u001B[1;32m    706\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_create_chat_result(response, generation_info)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_utils/_utils.py:274\u001B[0m, in \u001B[0;36mrequired_args.<locals>.inner.<locals>.wrapper\u001B[0;34m(*args, **kwargs)\u001B[0m\n\u001B[1;32m    272\u001B[0m             msg \u001B[38;5;241m=\u001B[39m \u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mMissing required argument: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mquote(missing[\u001B[38;5;241m0\u001B[39m])\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m    273\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mTypeError\u001B[39;00m(msg)\n\u001B[0;32m--> 274\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m func(\u001B[38;5;241m*\u001B[39margs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/resources/chat/completions.py:815\u001B[0m, in \u001B[0;36mCompletions.create\u001B[0;34m(self, messages, model, audio, frequency_penalty, function_call, functions, logit_bias, logprobs, max_completion_tokens, max_tokens, metadata, modalities, n, parallel_tool_calls, presence_penalty, response_format, seed, service_tier, stop, store, stream, stream_options, temperature, tool_choice, tools, top_logprobs, top_p, user, extra_headers, extra_query, extra_body, timeout)\u001B[0m\n\u001B[1;32m    775\u001B[0m \u001B[38;5;129m@required_args\u001B[39m([\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodel\u001B[39m\u001B[38;5;124m\"\u001B[39m], [\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodel\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstream\u001B[39m\u001B[38;5;124m\"\u001B[39m])\n\u001B[1;32m    776\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mcreate\u001B[39m(\n\u001B[1;32m    777\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    812\u001B[0m     timeout: \u001B[38;5;28mfloat\u001B[39m \u001B[38;5;241m|\u001B[39m httpx\u001B[38;5;241m.\u001B[39mTimeout \u001B[38;5;241m|\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m \u001B[38;5;241m|\u001B[39m NotGiven \u001B[38;5;241m=\u001B[39m NOT_GIVEN,\n\u001B[1;32m    813\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m ChatCompletion \u001B[38;5;241m|\u001B[39m Stream[ChatCompletionChunk]:\n\u001B[1;32m    814\u001B[0m     validate_response_format(response_format)\n\u001B[0;32m--> 815\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_post(\n\u001B[1;32m    816\u001B[0m         \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m/chat/completions\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[1;32m    817\u001B[0m         body\u001B[38;5;241m=\u001B[39mmaybe_transform(\n\u001B[1;32m    818\u001B[0m             {\n\u001B[1;32m    819\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: messages,\n\u001B[1;32m    820\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodel\u001B[39m\u001B[38;5;124m\"\u001B[39m: model,\n\u001B[1;32m    821\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124maudio\u001B[39m\u001B[38;5;124m\"\u001B[39m: audio,\n\u001B[1;32m    822\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfrequency_penalty\u001B[39m\u001B[38;5;124m\"\u001B[39m: frequency_penalty,\n\u001B[1;32m    823\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfunction_call\u001B[39m\u001B[38;5;124m\"\u001B[39m: function_call,\n\u001B[1;32m    824\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfunctions\u001B[39m\u001B[38;5;124m\"\u001B[39m: functions,\n\u001B[1;32m    825\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mlogit_bias\u001B[39m\u001B[38;5;124m\"\u001B[39m: logit_bias,\n\u001B[1;32m    826\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mlogprobs\u001B[39m\u001B[38;5;124m\"\u001B[39m: logprobs,\n\u001B[1;32m    827\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmax_completion_tokens\u001B[39m\u001B[38;5;124m\"\u001B[39m: max_completion_tokens,\n\u001B[1;32m    828\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmax_tokens\u001B[39m\u001B[38;5;124m\"\u001B[39m: max_tokens,\n\u001B[1;32m    829\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmetadata\u001B[39m\u001B[38;5;124m\"\u001B[39m: metadata,\n\u001B[1;32m    830\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodalities\u001B[39m\u001B[38;5;124m\"\u001B[39m: modalities,\n\u001B[1;32m    831\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mn\u001B[39m\u001B[38;5;124m\"\u001B[39m: n,\n\u001B[1;32m    832\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mparallel_tool_calls\u001B[39m\u001B[38;5;124m\"\u001B[39m: parallel_tool_calls,\n\u001B[1;32m    833\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mpresence_penalty\u001B[39m\u001B[38;5;124m\"\u001B[39m: presence_penalty,\n\u001B[1;32m    834\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mresponse_format\u001B[39m\u001B[38;5;124m\"\u001B[39m: response_format,\n\u001B[1;32m    835\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mseed\u001B[39m\u001B[38;5;124m\"\u001B[39m: seed,\n\u001B[1;32m    836\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mservice_tier\u001B[39m\u001B[38;5;124m\"\u001B[39m: service_tier,\n\u001B[1;32m    837\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstop\u001B[39m\u001B[38;5;124m\"\u001B[39m: stop,\n\u001B[1;32m    838\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstore\u001B[39m\u001B[38;5;124m\"\u001B[39m: store,\n\u001B[1;32m    839\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstream\u001B[39m\u001B[38;5;124m\"\u001B[39m: stream,\n\u001B[1;32m    840\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstream_options\u001B[39m\u001B[38;5;124m\"\u001B[39m: stream_options,\n\u001B[1;32m    841\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtemperature\u001B[39m\u001B[38;5;124m\"\u001B[39m: temperature,\n\u001B[1;32m    842\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtool_choice\u001B[39m\u001B[38;5;124m\"\u001B[39m: tool_choice,\n\u001B[1;32m    843\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtools\u001B[39m\u001B[38;5;124m\"\u001B[39m: tools,\n\u001B[1;32m    844\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtop_logprobs\u001B[39m\u001B[38;5;124m\"\u001B[39m: top_logprobs,\n\u001B[1;32m    845\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtop_p\u001B[39m\u001B[38;5;124m\"\u001B[39m: top_p,\n\u001B[1;32m    846\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124muser\u001B[39m\u001B[38;5;124m\"\u001B[39m: user,\n\u001B[1;32m    847\u001B[0m             },\n\u001B[1;32m    848\u001B[0m             completion_create_params\u001B[38;5;241m.\u001B[39mCompletionCreateParams,\n\u001B[1;32m    849\u001B[0m         ),\n\u001B[1;32m    850\u001B[0m         options\u001B[38;5;241m=\u001B[39mmake_request_options(\n\u001B[1;32m    851\u001B[0m             extra_headers\u001B[38;5;241m=\u001B[39mextra_headers, extra_query\u001B[38;5;241m=\u001B[39mextra_query, extra_body\u001B[38;5;241m=\u001B[39mextra_body, timeout\u001B[38;5;241m=\u001B[39mtimeout\n\u001B[1;32m    852\u001B[0m         ),\n\u001B[1;32m    853\u001B[0m         cast_to\u001B[38;5;241m=\u001B[39mChatCompletion,\n\u001B[1;32m    854\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28;01mFalse\u001B[39;00m,\n\u001B[1;32m    855\u001B[0m         stream_cls\u001B[38;5;241m=\u001B[39mStream[ChatCompletionChunk],\n\u001B[1;32m    856\u001B[0m     )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1277\u001B[0m, in \u001B[0;36mSyncAPIClient.post\u001B[0;34m(self, path, cast_to, body, options, files, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1263\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mpost\u001B[39m(\n\u001B[1;32m   1264\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m   1265\u001B[0m     path: \u001B[38;5;28mstr\u001B[39m,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m   1272\u001B[0m     stream_cls: \u001B[38;5;28mtype\u001B[39m[_StreamT] \u001B[38;5;241m|\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1273\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m ResponseT \u001B[38;5;241m|\u001B[39m _StreamT:\n\u001B[1;32m   1274\u001B[0m     opts \u001B[38;5;241m=\u001B[39m FinalRequestOptions\u001B[38;5;241m.\u001B[39mconstruct(\n\u001B[1;32m   1275\u001B[0m         method\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mpost\u001B[39m\u001B[38;5;124m\"\u001B[39m, url\u001B[38;5;241m=\u001B[39mpath, json_data\u001B[38;5;241m=\u001B[39mbody, files\u001B[38;5;241m=\u001B[39mto_httpx_files(files), \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39moptions\n\u001B[1;32m   1276\u001B[0m     )\n\u001B[0;32m-> 1277\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m cast(ResponseT, \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrequest(cast_to, opts, stream\u001B[38;5;241m=\u001B[39mstream, stream_cls\u001B[38;5;241m=\u001B[39mstream_cls))\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:954\u001B[0m, in \u001B[0;36mSyncAPIClient.request\u001B[0;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001B[0m\n\u001B[1;32m    951\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    952\u001B[0m     retries_taken \u001B[38;5;241m=\u001B[39m \u001B[38;5;241m0\u001B[39m\n\u001B[0;32m--> 954\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_request(\n\u001B[1;32m    955\u001B[0m     cast_to\u001B[38;5;241m=\u001B[39mcast_to,\n\u001B[1;32m    956\u001B[0m     options\u001B[38;5;241m=\u001B[39moptions,\n\u001B[1;32m    957\u001B[0m     stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m    958\u001B[0m     stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m    959\u001B[0m     retries_taken\u001B[38;5;241m=\u001B[39mretries_taken,\n\u001B[1;32m    960\u001B[0m )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1014\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1011\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mEncountered Exception\u001B[39m\u001B[38;5;124m\"\u001B[39m, exc_info\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m)\n\u001B[1;32m   1013\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m remaining_retries \u001B[38;5;241m>\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m-> 1014\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_retry_request(\n\u001B[1;32m   1015\u001B[0m         input_options,\n\u001B[1;32m   1016\u001B[0m         cast_to,\n\u001B[1;32m   1017\u001B[0m         retries_taken\u001B[38;5;241m=\u001B[39mretries_taken,\n\u001B[1;32m   1018\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1019\u001B[0m         stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1020\u001B[0m         response_headers\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1021\u001B[0m     )\n\u001B[1;32m   1023\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mRaising connection error\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m   1024\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m APIConnectionError(request\u001B[38;5;241m=\u001B[39mrequest) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01merr\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1092\u001B[0m, in \u001B[0;36mSyncAPIClient._retry_request\u001B[0;34m(self, options, cast_to, retries_taken, response_headers, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1088\u001B[0m \u001B[38;5;66;03m# In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a\u001B[39;00m\n\u001B[1;32m   1089\u001B[0m \u001B[38;5;66;03m# different thread if necessary.\u001B[39;00m\n\u001B[1;32m   1090\u001B[0m time\u001B[38;5;241m.\u001B[39msleep(timeout)\n\u001B[0;32m-> 1092\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_request(\n\u001B[1;32m   1093\u001B[0m     options\u001B[38;5;241m=\u001B[39moptions,\n\u001B[1;32m   1094\u001B[0m     cast_to\u001B[38;5;241m=\u001B[39mcast_to,\n\u001B[1;32m   1095\u001B[0m     retries_taken\u001B[38;5;241m=\u001B[39mretries_taken \u001B[38;5;241m+\u001B[39m \u001B[38;5;241m1\u001B[39m,\n\u001B[1;32m   1096\u001B[0m     stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1097\u001B[0m     stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1098\u001B[0m )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1014\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1011\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mEncountered Exception\u001B[39m\u001B[38;5;124m\"\u001B[39m, exc_info\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m)\n\u001B[1;32m   1013\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m remaining_retries \u001B[38;5;241m>\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m-> 1014\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_retry_request(\n\u001B[1;32m   1015\u001B[0m         input_options,\n\u001B[1;32m   1016\u001B[0m         cast_to,\n\u001B[1;32m   1017\u001B[0m         retries_taken\u001B[38;5;241m=\u001B[39mretries_taken,\n\u001B[1;32m   1018\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1019\u001B[0m         stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1020\u001B[0m         response_headers\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1021\u001B[0m     )\n\u001B[1;32m   1023\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mRaising connection error\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m   1024\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m APIConnectionError(request\u001B[38;5;241m=\u001B[39mrequest) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01merr\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1092\u001B[0m, in \u001B[0;36mSyncAPIClient._retry_request\u001B[0;34m(self, options, cast_to, retries_taken, response_headers, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1088\u001B[0m \u001B[38;5;66;03m# In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a\u001B[39;00m\n\u001B[1;32m   1089\u001B[0m \u001B[38;5;66;03m# different thread if necessary.\u001B[39;00m\n\u001B[1;32m   1090\u001B[0m time\u001B[38;5;241m.\u001B[39msleep(timeout)\n\u001B[0;32m-> 1092\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_request(\n\u001B[1;32m   1093\u001B[0m     options\u001B[38;5;241m=\u001B[39moptions,\n\u001B[1;32m   1094\u001B[0m     cast_to\u001B[38;5;241m=\u001B[39mcast_to,\n\u001B[1;32m   1095\u001B[0m     retries_taken\u001B[38;5;241m=\u001B[39mretries_taken \u001B[38;5;241m+\u001B[39m \u001B[38;5;241m1\u001B[39m,\n\u001B[1;32m   1096\u001B[0m     stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1097\u001B[0m     stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1098\u001B[0m )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1024\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1014\u001B[0m         \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_retry_request(\n\u001B[1;32m   1015\u001B[0m             input_options,\n\u001B[1;32m   1016\u001B[0m             cast_to,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m   1020\u001B[0m             response_headers\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1021\u001B[0m         )\n\u001B[1;32m   1023\u001B[0m     log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mRaising connection error\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[0;32m-> 1024\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m APIConnectionError(request\u001B[38;5;241m=\u001B[39mrequest) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01merr\u001B[39;00m\n\u001B[1;32m   1026\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\n\u001B[1;32m   1027\u001B[0m     \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mHTTP Response: \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;132;01m%i\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m'\u001B[39m,\n\u001B[1;32m   1028\u001B[0m     request\u001B[38;5;241m.\u001B[39mmethod,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m   1032\u001B[0m     response\u001B[38;5;241m.\u001B[39mheaders,\n\u001B[1;32m   1033\u001B[0m )\n\u001B[1;32m   1034\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrequest_id: \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m\"\u001B[39m, response\u001B[38;5;241m.\u001B[39mheaders\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mx-request-id\u001B[39m\u001B[38;5;124m\"\u001B[39m))\n",
      "\u001B[0;31mAPIConnectionError\u001B[0m: Connection error."
     ]
    }
   ],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from typing import Annotated, Literal\n",
    "\n",
    "from langchain_core.messages import AIMessage\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "from pydantic import BaseModel, Field\n",
    "from typing_extensions import TypedDict\n",
    "\n",
    "from langgraph.graph import END, StateGraph, START\n",
    "from langgraph.graph.message import AnyMessage, add_messages\n",
    "\n",
    "\n",
    "def load_tables_schema_tool_call_node(state: State, config) -> dict[str, list[AIMessage]]:\n",
    "    return {\n",
    "        \"messages\": [\n",
    "            AIMessage(\n",
    "                content=\"\",\n",
    "                tool_calls=[\n",
    "                    {\n",
    "                        \"name\": get_schema_tool.name,\n",
    "                        \"args\": {\"table_names\": \"Album,Employee\"},\n",
    "                        #{\"table_names\": state[\"messages\"][-1].tool_calls[0].args[\"table_names\"]},\n",
    "                        \"id\": \"tool_abcd124\",\n",
    "                    }\n",
    "                ]\n",
    "            )\n",
    "        ]\n",
    "    }\n",
    "\n",
    "# SQL语句生成\n",
    "def query_generate_node(state: State, config):\n",
    "    \"\"\"SQL语句生成\"\"\"\n",
    "    dialect = db.dialect\n",
    "    limit = 5\n",
    "    #不要使用除SubmitFinalAnswer之外的任何工具来提交最终答案，最终答案只返回查询语句。\n",
    "    query_generate_template = f\"\"\"你是一个注重细节的SQL专家。\n",
    "    \n",
    "    给定一个问题，输出一个语法正确的{dialect}查询语句，然后返回查询语句。\n",
    "    \n",
    "    不要使用工具来提交最终答案，最终答案只返回查询语句。\n",
    "    \n",
    "    在生成查询时：\n",
    "    \n",
    "    输出能够回答输入问题的SQL查询语句。\n",
    "    \n",
    "    除非用户指定了他们希望获得的具体示例数量，否则应始终将查询结果限制在最多{limit}个。 可以根据相关列对结果进行排序，以返回数据库中最佳的示例。 永远不要查询特定表中的所有列，只根据问题要求查询相关列。\n",
    "    \n",
    "    如果在执行查询时出现错误，请重写查询并再次尝试。\n",
    "    \n",
    "    如果得到空的结果集，应尝试重写查询以获得非空的结果集。 如果没有足够的信息来回答查询，千万不要编造答案...只需说明你没有足够的信息。\n",
    "    \n",
    "    如果你有足够的信息来回答输入的问题，只需调用适当的工具将最终答案提交给用户。\n",
    "        \n",
    "    不要对数据库执行任何DML语句（如INSERT、UPDATE、DELETE、DROP等）。\n",
    "    \"\"\"\n",
    "    #     如果表字段中存在'Email'字段，请将该表查询条件增加'Email'等于'122@123.com'条件\n",
    "\n",
    "    query_generate_prompt = ChatPromptTemplate.from_messages(\n",
    "        [(\"system\", query_generate_template), (\"placeholder\", \"{messages}\")]\n",
    "    )\n",
    "\n",
    "    # llm = query_generate_prompt | ChatOpenAI(\n",
    "    #     # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\n",
    "    #     openai_api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\n",
    "    #     openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "    #     model_name=\"qwen-max\",\n",
    "    #     verbose=True, temperature=0\n",
    "    # ).bind_tools([sql_db_query_tool])\n",
    "    llm = query_generate_prompt | ChatOpenAI(\n",
    "        # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\n",
    "        api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\n",
    "        # openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "        model=\"qwen-max\",\n",
    "        top_p=0.9,\n",
    "        verbose=True, temperature=0.5\n",
    "    ).bind_tools([sql_db_query_tool])\n",
    "\n",
    "    message = llm.invoke(state)\n",
    "\n",
    "    return {\"messages\": [message] }\n",
    "\n",
    "query_generate_node({\"messages\": [(\"user\", \"我需要2人生日是1970年之前的老干部\")]}, None)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:12:25.158471Z",
     "start_time": "2024-11-22T09:12:21.314027Z"
    }
   },
   "id": "bb50b08d9aa43a1d",
   "execution_count": 415
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "def should_continue_with_schema(state)->Literal[END,\"query_generate\"]:\n",
    "    \"\"\"判断是否需要加载表结构是否正常\"\"\"\n",
    "    last_message = state[\"messages\"][-1]\n",
    "    if not last_message.content.startswith(\"Error:\"):\n",
    "        return \"query_generate\"\n",
    "    else:\n",
    "        print(f\"schema获取异常 {last_message.content}\")\n",
    "        return END\n",
    "\n",
    "def should_continue_with_query(state) -> Literal[END, \"query_execute_tools\", \"query_generate\"]:\n",
    "    \"\"\"判断是否继续执行下一步操作\"\"\"\n",
    "    # todo 待完善\n",
    "    messages = state[\"messages\"]\n",
    "    last_message = messages[-1]\n",
    "    # If there is a tool call, then we finish\n",
    "    if getattr(last_message, \"tool_calls\", None):\n",
    "        return END\n",
    "    if last_message.content.startswith(\"Error:\"):\n",
    "        return \"query_generate\"\n",
    "    else:\n",
    "        return \"query_execute_tools\"\n",
    "\n",
    "workflow = StateGraph(State)\n",
    "workflow.add_node(\"tables_schema_tool_call\", load_tables_schema_tool_call_node)\n",
    "workflow.add_node(\"schema_tool\", create_tool_node_with_fallback([get_schema_tool]))\n",
    "workflow.add_node(\"query_generate\", query_generate_node)\n",
    "# workflow.add_node(\"query_execute_tools\", create_tool_node_with_fallback([sql_db_query_tool]))\n",
    "\n",
    "workflow.add_edge(START, \"tables_schema_tool_call\")\n",
    "workflow.add_edge(\"tables_schema_tool_call\", \"schema_tool\")\n",
    "workflow.add_edge(\"schema_tool\", \"query_generate\")\n",
    "# workflow.add_edge(\"query_generate\", \"query_execute_tools\")\n",
    "\n",
    "# 边策略\n",
    "# workflow.add_conditional_edges(\n",
    "#                 \"schema_tool\",\n",
    "#             should_continue_with_schema\n",
    "#             )\n",
    "# 边策略\n",
    "# workflow.add_conditional_edges(\n",
    "#             \"query_generate\",\n",
    "#             should_continue_with_query\n",
    "#         )\n",
    "workflow.add_edge(\"query_generate\",END)\n",
    "\n",
    "\n",
    "graph = workflow.compile()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:13:17.604568Z",
     "start_time": "2024-11-22T09:13:17.589710Z"
    }
   },
   "id": "705eb2a4a422c4aa",
   "execution_count": 418
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from IPython.display import Image, display\n",
    "from langchain_core.runnables.graph import MermaidDrawMethod\n",
    "\n",
    "display(\n",
    "    Image(\n",
    "        graph.get_graph().draw_mermaid_png(\n",
    "            draw_method=MermaidDrawMethod.API,\n",
    "        )\n",
    "    )\n",
    ")"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "5303410dbfc0e181",
   "execution_count": null
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Event:{'tables_schema_tool_call': {'messages': [AIMessage(content='', additional_kwargs={}, response_metadata={}, id='e6957b4e-19e8-4049-9384-4aba3e7ee7d9', tool_calls=[{'name': 'sql_db_schema', 'args': {'table_names': 'Album,Employee'}, 'id': 'tool_abcd124', 'type': 'tool_call'}])]}}\n",
      "Event:{'schema_tool': {'messages': [ToolMessage(content='\\nCREATE TABLE \"Album\" (\\n\\t\"AlbumId\" INTEGER NOT NULL, \\n\\t\"Title\" NVARCHAR(160) NOT NULL, \\n\\t\"ArtistId\" INTEGER NOT NULL, \\n\\tPRIMARY KEY (\"AlbumId\"), \\n\\tFOREIGN KEY(\"ArtistId\") REFERENCES \"Artist\" (\"ArtistId\")\\n)\\n\\n/*\\n3 rows from Album table:\\nAlbumId\\tTitle\\tArtistId\\n1\\tFor Those About To Rock We Salute You\\t1\\n2\\tBalls to the Wall\\t2\\n3\\tRestless and Wild\\t2\\n*/\\n\\n\\nCREATE TABLE \"Employee\" (\\n\\t\"EmployeeId\" INTEGER NOT NULL, \\n\\t\"LastName\" NVARCHAR(20) NOT NULL, \\n\\t\"FirstName\" NVARCHAR(20) NOT NULL, \\n\\t\"Title\" NVARCHAR(30), \\n\\t\"ReportsTo\" INTEGER, \\n\\t\"BirthDate\" DATETIME, \\n\\t\"HireDate\" DATETIME, \\n\\t\"Address\" NVARCHAR(70), \\n\\t\"City\" NVARCHAR(40), \\n\\t\"State\" NVARCHAR(40), \\n\\t\"Country\" NVARCHAR(40), \\n\\t\"PostalCode\" NVARCHAR(10), \\n\\t\"Phone\" NVARCHAR(24), \\n\\t\"Fax\" NVARCHAR(24), \\n\\t\"Email\" NVARCHAR(60), \\n\\tPRIMARY KEY (\"EmployeeId\"), \\n\\tFOREIGN KEY(\"ReportsTo\") REFERENCES \"Employee\" (\"EmployeeId\")\\n)\\n\\n/*\\n3 rows from Employee table:\\nEmployeeId\\tLastName\\tFirstName\\tTitle\\tReportsTo\\tBirthDate\\tHireDate\\tAddress\\tCity\\tState\\tCountry\\tPostalCode\\tPhone\\tFax\\tEmail\\n1\\tAdams\\tAndrew\\tGeneral Manager\\tNone\\t1962-02-18 00:00:00\\t2002-08-14 00:00:00\\t11120 Jasper Ave NW\\tEdmonton\\tAB\\tCanada\\tT5K 2N1\\t+1 (780) 428-9482\\t+1 (780) 428-3457\\tandrew@chinookcorp.com\\n2\\tEdwards\\tNancy\\tSales Manager\\t1\\t1958-12-08 00:00:00\\t2002-05-01 00:00:00\\t825 8 Ave SW\\tCalgary\\tAB\\tCanada\\tT2P 2T3\\t+1 (403) 262-3443\\t+1 (403) 262-3322\\tnancy@chinookcorp.com\\n3\\tPeacock\\tJane\\tSales Support Agent\\t2\\t1973-08-29 00:00:00\\t2002-04-01 00:00:00\\t1111 6 Ave SW\\tCalgary\\tAB\\tCanada\\tT2P 5M5\\t+1 (403) 262-3443\\t+1 (403) 262-6712\\tjane@chinookcorp.com\\n*/', name='sql_db_schema', id='7a919e68-1ed1-44fb-a47b-63752373e5be', tool_call_id='tool_abcd124')]}}\n"
     ]
    },
    {
     "ename": "APIConnectionError",
     "evalue": "Connection error.",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mConnectError\u001B[0m                              Traceback (most recent call last)",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:72\u001B[0m, in \u001B[0;36mmap_httpcore_exceptions\u001B[0;34m()\u001B[0m\n\u001B[1;32m     71\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m---> 72\u001B[0m     \u001B[38;5;28;01myield\u001B[39;00m\n\u001B[1;32m     73\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:236\u001B[0m, in \u001B[0;36mHTTPTransport.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    235\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m map_httpcore_exceptions():\n\u001B[0;32m--> 236\u001B[0m     resp \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_pool\u001B[38;5;241m.\u001B[39mhandle_request(req)\n\u001B[1;32m    238\u001B[0m \u001B[38;5;28;01massert\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(resp\u001B[38;5;241m.\u001B[39mstream, typing\u001B[38;5;241m.\u001B[39mIterable)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:216\u001B[0m, in \u001B[0;36mConnectionPool.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    215\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_close_connections(closing)\n\u001B[0;32m--> 216\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m exc \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m    218\u001B[0m \u001B[38;5;66;03m# Return the response. Note that in this case we still have to manage\u001B[39;00m\n\u001B[1;32m    219\u001B[0m \u001B[38;5;66;03m# the point at which the response is closed.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:196\u001B[0m, in \u001B[0;36mConnectionPool.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    194\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m    195\u001B[0m     \u001B[38;5;66;03m# Send the request on the assigned connection.\u001B[39;00m\n\u001B[0;32m--> 196\u001B[0m     response \u001B[38;5;241m=\u001B[39m connection\u001B[38;5;241m.\u001B[39mhandle_request(\n\u001B[1;32m    197\u001B[0m         pool_request\u001B[38;5;241m.\u001B[39mrequest\n\u001B[1;32m    198\u001B[0m     )\n\u001B[1;32m    199\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m ConnectionNotAvailable:\n\u001B[1;32m    200\u001B[0m     \u001B[38;5;66;03m# In some cases a connection may initially be available to\u001B[39;00m\n\u001B[1;32m    201\u001B[0m     \u001B[38;5;66;03m# handle a request, but then become unavailable.\u001B[39;00m\n\u001B[1;32m    202\u001B[0m     \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[1;32m    203\u001B[0m     \u001B[38;5;66;03m# In this case we clear the connection and try again.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection.py:99\u001B[0m, in \u001B[0;36mHTTPConnection.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m     98\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connect_failed \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mTrue\u001B[39;00m\n\u001B[0;32m---> 99\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m exc\n\u001B[1;32m    101\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connection\u001B[38;5;241m.\u001B[39mhandle_request(request)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection.py:76\u001B[0m, in \u001B[0;36mHTTPConnection.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m     75\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connection \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[0;32m---> 76\u001B[0m     stream \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_connect(request)\n\u001B[1;32m     78\u001B[0m     ssl_object \u001B[38;5;241m=\u001B[39m stream\u001B[38;5;241m.\u001B[39mget_extra_info(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mssl_object\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_sync/connection.py:122\u001B[0m, in \u001B[0;36mHTTPConnection._connect\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    121\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m Trace(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mconnect_tcp\u001B[39m\u001B[38;5;124m\"\u001B[39m, logger, request, kwargs) \u001B[38;5;28;01mas\u001B[39;00m trace:\n\u001B[0;32m--> 122\u001B[0m     stream \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_network_backend\u001B[38;5;241m.\u001B[39mconnect_tcp(\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    123\u001B[0m     trace\u001B[38;5;241m.\u001B[39mreturn_value \u001B[38;5;241m=\u001B[39m stream\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_backends/sync.py:205\u001B[0m, in \u001B[0;36mSyncBackend.connect_tcp\u001B[0;34m(self, host, port, timeout, local_address, socket_options)\u001B[0m\n\u001B[1;32m    200\u001B[0m exc_map: ExceptionMapping \u001B[38;5;241m=\u001B[39m {\n\u001B[1;32m    201\u001B[0m     socket\u001B[38;5;241m.\u001B[39mtimeout: ConnectTimeout,\n\u001B[1;32m    202\u001B[0m     \u001B[38;5;167;01mOSError\u001B[39;00m: ConnectError,\n\u001B[1;32m    203\u001B[0m }\n\u001B[0;32m--> 205\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m map_exceptions(exc_map):\n\u001B[1;32m    206\u001B[0m     sock \u001B[38;5;241m=\u001B[39m socket\u001B[38;5;241m.\u001B[39mcreate_connection(\n\u001B[1;32m    207\u001B[0m         address,\n\u001B[1;32m    208\u001B[0m         timeout,\n\u001B[1;32m    209\u001B[0m         source_address\u001B[38;5;241m=\u001B[39msource_address,\n\u001B[1;32m    210\u001B[0m     )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/contextlib.py:158\u001B[0m, in \u001B[0;36m_GeneratorContextManager.__exit__\u001B[0;34m(self, typ, value, traceback)\u001B[0m\n\u001B[1;32m    157\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 158\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgen\u001B[38;5;241m.\u001B[39mthrow(value)\n\u001B[1;32m    159\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mStopIteration\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n\u001B[1;32m    160\u001B[0m     \u001B[38;5;66;03m# Suppress StopIteration *unless* it's the same exception that\u001B[39;00m\n\u001B[1;32m    161\u001B[0m     \u001B[38;5;66;03m# was passed to throw().  This prevents a StopIteration\u001B[39;00m\n\u001B[1;32m    162\u001B[0m     \u001B[38;5;66;03m# raised inside the \"with\" statement from being suppressed.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpcore/_exceptions.py:14\u001B[0m, in \u001B[0;36mmap_exceptions\u001B[0;34m(map)\u001B[0m\n\u001B[1;32m     13\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(exc, from_exc):\n\u001B[0;32m---> 14\u001B[0m         \u001B[38;5;28;01mraise\u001B[39;00m to_exc(exc) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mexc\u001B[39;00m\n\u001B[1;32m     15\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m\n",
      "\u001B[0;31mConnectError\u001B[0m: [Errno 61] Connection refused",
      "\nThe above exception was the direct cause of the following exception:\n",
      "\u001B[0;31mConnectError\u001B[0m                              Traceback (most recent call last)",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:990\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m    989\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 990\u001B[0m     response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_client\u001B[38;5;241m.\u001B[39msend(\n\u001B[1;32m    991\u001B[0m         request,\n\u001B[1;32m    992\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_should_stream_response_body(request\u001B[38;5;241m=\u001B[39mrequest),\n\u001B[1;32m    993\u001B[0m         \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m    994\u001B[0m     )\n\u001B[1;32m    995\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m httpx\u001B[38;5;241m.\u001B[39mTimeoutException \u001B[38;5;28;01mas\u001B[39;00m err:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:926\u001B[0m, in \u001B[0;36mClient.send\u001B[0;34m(self, request, stream, auth, follow_redirects)\u001B[0m\n\u001B[1;32m    924\u001B[0m auth \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_build_request_auth(request, auth)\n\u001B[0;32m--> 926\u001B[0m response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_send_handling_auth(\n\u001B[1;32m    927\u001B[0m     request,\n\u001B[1;32m    928\u001B[0m     auth\u001B[38;5;241m=\u001B[39mauth,\n\u001B[1;32m    929\u001B[0m     follow_redirects\u001B[38;5;241m=\u001B[39mfollow_redirects,\n\u001B[1;32m    930\u001B[0m     history\u001B[38;5;241m=\u001B[39m[],\n\u001B[1;32m    931\u001B[0m )\n\u001B[1;32m    932\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:954\u001B[0m, in \u001B[0;36mClient._send_handling_auth\u001B[0;34m(self, request, auth, follow_redirects, history)\u001B[0m\n\u001B[1;32m    953\u001B[0m \u001B[38;5;28;01mwhile\u001B[39;00m \u001B[38;5;28;01mTrue\u001B[39;00m:\n\u001B[0;32m--> 954\u001B[0m     response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_send_handling_redirects(\n\u001B[1;32m    955\u001B[0m         request,\n\u001B[1;32m    956\u001B[0m         follow_redirects\u001B[38;5;241m=\u001B[39mfollow_redirects,\n\u001B[1;32m    957\u001B[0m         history\u001B[38;5;241m=\u001B[39mhistory,\n\u001B[1;32m    958\u001B[0m     )\n\u001B[1;32m    959\u001B[0m     \u001B[38;5;28;01mtry\u001B[39;00m:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:991\u001B[0m, in \u001B[0;36mClient._send_handling_redirects\u001B[0;34m(self, request, follow_redirects, history)\u001B[0m\n\u001B[1;32m    989\u001B[0m     hook(request)\n\u001B[0;32m--> 991\u001B[0m response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_send_single_request(request)\n\u001B[1;32m    992\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_client.py:1027\u001B[0m, in \u001B[0;36mClient._send_single_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m   1026\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m request_context(request\u001B[38;5;241m=\u001B[39mrequest):\n\u001B[0;32m-> 1027\u001B[0m     response \u001B[38;5;241m=\u001B[39m transport\u001B[38;5;241m.\u001B[39mhandle_request(request)\n\u001B[1;32m   1029\u001B[0m \u001B[38;5;28;01massert\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(response\u001B[38;5;241m.\u001B[39mstream, SyncByteStream)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:235\u001B[0m, in \u001B[0;36mHTTPTransport.handle_request\u001B[0;34m(self, request)\u001B[0m\n\u001B[1;32m    223\u001B[0m req \u001B[38;5;241m=\u001B[39m httpcore\u001B[38;5;241m.\u001B[39mRequest(\n\u001B[1;32m    224\u001B[0m     method\u001B[38;5;241m=\u001B[39mrequest\u001B[38;5;241m.\u001B[39mmethod,\n\u001B[1;32m    225\u001B[0m     url\u001B[38;5;241m=\u001B[39mhttpcore\u001B[38;5;241m.\u001B[39mURL(\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    233\u001B[0m     extensions\u001B[38;5;241m=\u001B[39mrequest\u001B[38;5;241m.\u001B[39mextensions,\n\u001B[1;32m    234\u001B[0m )\n\u001B[0;32m--> 235\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m map_httpcore_exceptions():\n\u001B[1;32m    236\u001B[0m     resp \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_pool\u001B[38;5;241m.\u001B[39mhandle_request(req)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/contextlib.py:158\u001B[0m, in \u001B[0;36m_GeneratorContextManager.__exit__\u001B[0;34m(self, typ, value, traceback)\u001B[0m\n\u001B[1;32m    157\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 158\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgen\u001B[38;5;241m.\u001B[39mthrow(value)\n\u001B[1;32m    159\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mStopIteration\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n\u001B[1;32m    160\u001B[0m     \u001B[38;5;66;03m# Suppress StopIteration *unless* it's the same exception that\u001B[39;00m\n\u001B[1;32m    161\u001B[0m     \u001B[38;5;66;03m# was passed to throw().  This prevents a StopIteration\u001B[39;00m\n\u001B[1;32m    162\u001B[0m     \u001B[38;5;66;03m# raised inside the \"with\" statement from being suppressed.\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/httpx/_transports/default.py:89\u001B[0m, in \u001B[0;36mmap_httpcore_exceptions\u001B[0;34m()\u001B[0m\n\u001B[1;32m     88\u001B[0m message \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mstr\u001B[39m(exc)\n\u001B[0;32m---> 89\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m mapped_exc(message) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mexc\u001B[39;00m\n",
      "\u001B[0;31mConnectError\u001B[0m: [Errno 61] Connection refused",
      "\nThe above exception was the direct cause of the following exception:\n",
      "\u001B[0;31mAPIConnectionError\u001B[0m                        Traceback (most recent call last)",
      "Cell \u001B[0;32mIn[419], line 5\u001B[0m\n\u001B[1;32m      1\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mlangchain_core\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mmessages\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m BaseMessage\n\u001B[1;32m      3\u001B[0m \u001B[38;5;66;03m# graph.invoke({\"messages\": [(\"user\", \"我需要10人生日是1970年之前的员工\")]})\u001B[39;00m\n\u001B[0;32m----> 5\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m event \u001B[38;5;129;01min\u001B[39;00m graph\u001B[38;5;241m.\u001B[39mstream(\n\u001B[1;32m      6\u001B[0m     {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124muser\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m我需要2人生日是2000年之前的员工\u001B[39m\u001B[38;5;124m\"\u001B[39m)]}\n\u001B[1;32m      7\u001B[0m ):\n\u001B[1;32m      8\u001B[0m     \u001B[38;5;28mprint\u001B[39m(\u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mEvent:\u001B[39m\u001B[38;5;132;01m{\u001B[39;00mevent\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m\"\u001B[39m)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/__init__.py:1328\u001B[0m, in \u001B[0;36mPregel.stream\u001B[0;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, subgraphs)\u001B[0m\n\u001B[1;32m   1317\u001B[0m     \u001B[38;5;66;03m# Similarly to Bulk Synchronous Parallel / Pregel model\u001B[39;00m\n\u001B[1;32m   1318\u001B[0m     \u001B[38;5;66;03m# computation proceeds in steps, while there are channel updates\u001B[39;00m\n\u001B[1;32m   1319\u001B[0m     \u001B[38;5;66;03m# channel updates from step N are only visible in step N+1\u001B[39;00m\n\u001B[1;32m   1320\u001B[0m     \u001B[38;5;66;03m# channels are guaranteed to be immutable for the duration of the step,\u001B[39;00m\n\u001B[1;32m   1321\u001B[0m     \u001B[38;5;66;03m# with channel updates applied only at the transition between steps\u001B[39;00m\n\u001B[1;32m   1322\u001B[0m     \u001B[38;5;28;01mwhile\u001B[39;00m loop\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1323\u001B[0m         input_keys\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39minput_channels,\n\u001B[1;32m   1324\u001B[0m         interrupt_before\u001B[38;5;241m=\u001B[39minterrupt_before_,\n\u001B[1;32m   1325\u001B[0m         interrupt_after\u001B[38;5;241m=\u001B[39minterrupt_after_,\n\u001B[1;32m   1326\u001B[0m         manager\u001B[38;5;241m=\u001B[39mrun_manager,\n\u001B[1;32m   1327\u001B[0m     ):\n\u001B[0;32m-> 1328\u001B[0m         \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m runner\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1329\u001B[0m             loop\u001B[38;5;241m.\u001B[39mtasks\u001B[38;5;241m.\u001B[39mvalues(),\n\u001B[1;32m   1330\u001B[0m             timeout\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstep_timeout,\n\u001B[1;32m   1331\u001B[0m             retry_policy\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mretry_policy,\n\u001B[1;32m   1332\u001B[0m             get_waiter\u001B[38;5;241m=\u001B[39mget_waiter,\n\u001B[1;32m   1333\u001B[0m         ):\n\u001B[1;32m   1334\u001B[0m             \u001B[38;5;66;03m# emit output\u001B[39;00m\n\u001B[1;32m   1335\u001B[0m             \u001B[38;5;28;01myield from\u001B[39;00m output()\n\u001B[1;32m   1336\u001B[0m \u001B[38;5;66;03m# emit output\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/runner.py:58\u001B[0m, in \u001B[0;36mPregelRunner.tick\u001B[0;34m(self, tasks, reraise, timeout, retry_policy, get_waiter)\u001B[0m\n\u001B[1;32m     56\u001B[0m t \u001B[38;5;241m=\u001B[39m tasks[\u001B[38;5;241m0\u001B[39m]\n\u001B[1;32m     57\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m---> 58\u001B[0m     run_with_retry(t, retry_policy)\n\u001B[1;32m     59\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mcommit(t, \u001B[38;5;28;01mNone\u001B[39;00m)\n\u001B[1;32m     60\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/retry.py:29\u001B[0m, in \u001B[0;36mrun_with_retry\u001B[0;34m(task, retry_policy)\u001B[0m\n\u001B[1;32m     27\u001B[0m task\u001B[38;5;241m.\u001B[39mwrites\u001B[38;5;241m.\u001B[39mclear()\n\u001B[1;32m     28\u001B[0m \u001B[38;5;66;03m# run the task\u001B[39;00m\n\u001B[0;32m---> 29\u001B[0m task\u001B[38;5;241m.\u001B[39mproc\u001B[38;5;241m.\u001B[39minvoke(task\u001B[38;5;241m.\u001B[39minput, config)\n\u001B[1;32m     30\u001B[0m \u001B[38;5;66;03m# if successful, end\u001B[39;00m\n\u001B[1;32m     31\u001B[0m \u001B[38;5;28;01mbreak\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:410\u001B[0m, in \u001B[0;36mRunnableSeq.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    408\u001B[0m context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[1;32m    409\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m i \u001B[38;5;241m==\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m--> 410\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    411\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    412\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:184\u001B[0m, in \u001B[0;36mRunnableCallable.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    182\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    183\u001B[0m     context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[0;32m--> 184\u001B[0m     ret \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mfunc, \u001B[38;5;28minput\u001B[39m, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    185\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(ret, Runnable) \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrecurse:\n\u001B[1;32m    186\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m ret\u001B[38;5;241m.\u001B[39minvoke(\u001B[38;5;28minput\u001B[39m, config)\n",
      "Cell \u001B[0;32mIn[415], line 79\u001B[0m, in \u001B[0;36mquery_generate_node\u001B[0;34m(state, config)\u001B[0m\n\u001B[1;32m     63\u001B[0m \u001B[38;5;66;03m# llm = query_generate_prompt | ChatOpenAI(\u001B[39;00m\n\u001B[1;32m     64\u001B[0m \u001B[38;5;66;03m#     # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\u001B[39;00m\n\u001B[1;32m     65\u001B[0m \u001B[38;5;66;03m#     openai_api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\u001B[39;00m\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m     68\u001B[0m \u001B[38;5;66;03m#     verbose=True, temperature=0\u001B[39;00m\n\u001B[1;32m     69\u001B[0m \u001B[38;5;66;03m# ).bind_tools([sql_db_query_tool])\u001B[39;00m\n\u001B[1;32m     70\u001B[0m llm \u001B[38;5;241m=\u001B[39m query_generate_prompt \u001B[38;5;241m|\u001B[39m ChatOpenAI(\n\u001B[1;32m     71\u001B[0m     \u001B[38;5;66;03m# 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\u001B[39;00m\n\u001B[1;32m     72\u001B[0m     api_key\u001B[38;5;241m=\u001B[39mos\u001B[38;5;241m.\u001B[39mgetenv(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mDASHSCOPE_API_KEY\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m     76\u001B[0m     verbose\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m, temperature\u001B[38;5;241m=\u001B[39m\u001B[38;5;241m0.5\u001B[39m\n\u001B[1;32m     77\u001B[0m )\u001B[38;5;241m.\u001B[39mbind_tools([sql_db_query_tool])\n\u001B[0;32m---> 79\u001B[0m message \u001B[38;5;241m=\u001B[39m llm\u001B[38;5;241m.\u001B[39minvoke(state)\n\u001B[1;32m     81\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [message] }\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/runnables/base.py:3024\u001B[0m, in \u001B[0;36mRunnableSequence.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m   3022\u001B[0m             \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m   3023\u001B[0m         \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m-> 3024\u001B[0m             \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config)\n\u001B[1;32m   3025\u001B[0m \u001B[38;5;66;03m# finish the root run\u001B[39;00m\n\u001B[1;32m   3026\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mBaseException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m e:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/runnables/base.py:5354\u001B[0m, in \u001B[0;36mRunnableBindingBase.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m   5348\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21minvoke\u001B[39m(\n\u001B[1;32m   5349\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m   5350\u001B[0m     \u001B[38;5;28minput\u001B[39m: Input,\n\u001B[1;32m   5351\u001B[0m     config: Optional[RunnableConfig] \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   5352\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Optional[Any],\n\u001B[1;32m   5353\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m Output:\n\u001B[0;32m-> 5354\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mbound\u001B[38;5;241m.\u001B[39minvoke(\n\u001B[1;32m   5355\u001B[0m         \u001B[38;5;28minput\u001B[39m,\n\u001B[1;32m   5356\u001B[0m         \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_merge_configs(config),\n\u001B[1;32m   5357\u001B[0m         \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39m{\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mkwargs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs},\n\u001B[1;32m   5358\u001B[0m     )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:286\u001B[0m, in \u001B[0;36mBaseChatModel.invoke\u001B[0;34m(self, input, config, stop, **kwargs)\u001B[0m\n\u001B[1;32m    275\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21minvoke\u001B[39m(\n\u001B[1;32m    276\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m    277\u001B[0m     \u001B[38;5;28minput\u001B[39m: LanguageModelInput,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    281\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Any,\n\u001B[1;32m    282\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m BaseMessage:\n\u001B[1;32m    283\u001B[0m     config \u001B[38;5;241m=\u001B[39m ensure_config(config)\n\u001B[1;32m    284\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m cast(\n\u001B[1;32m    285\u001B[0m         ChatGeneration,\n\u001B[0;32m--> 286\u001B[0m         \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgenerate_prompt(\n\u001B[1;32m    287\u001B[0m             [\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_convert_input(\u001B[38;5;28minput\u001B[39m)],\n\u001B[1;32m    288\u001B[0m             stop\u001B[38;5;241m=\u001B[39mstop,\n\u001B[1;32m    289\u001B[0m             callbacks\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcallbacks\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    290\u001B[0m             tags\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtags\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    291\u001B[0m             metadata\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmetadata\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    292\u001B[0m             run_name\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrun_name\u001B[39m\u001B[38;5;124m\"\u001B[39m),\n\u001B[1;32m    293\u001B[0m             run_id\u001B[38;5;241m=\u001B[39mconfig\u001B[38;5;241m.\u001B[39mpop(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrun_id\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;28;01mNone\u001B[39;00m),\n\u001B[1;32m    294\u001B[0m             \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m    295\u001B[0m         )\u001B[38;5;241m.\u001B[39mgenerations[\u001B[38;5;241m0\u001B[39m][\u001B[38;5;241m0\u001B[39m],\n\u001B[1;32m    296\u001B[0m     )\u001B[38;5;241m.\u001B[39mmessage\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:786\u001B[0m, in \u001B[0;36mBaseChatModel.generate_prompt\u001B[0;34m(self, prompts, stop, callbacks, **kwargs)\u001B[0m\n\u001B[1;32m    778\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mgenerate_prompt\u001B[39m(\n\u001B[1;32m    779\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m    780\u001B[0m     prompts: \u001B[38;5;28mlist\u001B[39m[PromptValue],\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    783\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Any,\n\u001B[1;32m    784\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m LLMResult:\n\u001B[1;32m    785\u001B[0m     prompt_messages \u001B[38;5;241m=\u001B[39m [p\u001B[38;5;241m.\u001B[39mto_messages() \u001B[38;5;28;01mfor\u001B[39;00m p \u001B[38;5;129;01min\u001B[39;00m prompts]\n\u001B[0;32m--> 786\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgenerate(prompt_messages, stop\u001B[38;5;241m=\u001B[39mstop, callbacks\u001B[38;5;241m=\u001B[39mcallbacks, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:643\u001B[0m, in \u001B[0;36mBaseChatModel.generate\u001B[0;34m(self, messages, stop, callbacks, tags, metadata, run_name, run_id, **kwargs)\u001B[0m\n\u001B[1;32m    641\u001B[0m         \u001B[38;5;28;01mif\u001B[39;00m run_managers:\n\u001B[1;32m    642\u001B[0m             run_managers[i]\u001B[38;5;241m.\u001B[39mon_llm_error(e, response\u001B[38;5;241m=\u001B[39mLLMResult(generations\u001B[38;5;241m=\u001B[39m[]))\n\u001B[0;32m--> 643\u001B[0m         \u001B[38;5;28;01mraise\u001B[39;00m e\n\u001B[1;32m    644\u001B[0m flattened_outputs \u001B[38;5;241m=\u001B[39m [\n\u001B[1;32m    645\u001B[0m     LLMResult(generations\u001B[38;5;241m=\u001B[39m[res\u001B[38;5;241m.\u001B[39mgenerations], llm_output\u001B[38;5;241m=\u001B[39mres\u001B[38;5;241m.\u001B[39mllm_output)  \u001B[38;5;66;03m# type: ignore[list-item]\u001B[39;00m\n\u001B[1;32m    646\u001B[0m     \u001B[38;5;28;01mfor\u001B[39;00m res \u001B[38;5;129;01min\u001B[39;00m results\n\u001B[1;32m    647\u001B[0m ]\n\u001B[1;32m    648\u001B[0m llm_output \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_combine_llm_outputs([res\u001B[38;5;241m.\u001B[39mllm_output \u001B[38;5;28;01mfor\u001B[39;00m res \u001B[38;5;129;01min\u001B[39;00m results])\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:633\u001B[0m, in \u001B[0;36mBaseChatModel.generate\u001B[0;34m(self, messages, stop, callbacks, tags, metadata, run_name, run_id, **kwargs)\u001B[0m\n\u001B[1;32m    630\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m i, m \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28menumerate\u001B[39m(messages):\n\u001B[1;32m    631\u001B[0m     \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m    632\u001B[0m         results\u001B[38;5;241m.\u001B[39mappend(\n\u001B[0;32m--> 633\u001B[0m             \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate_with_cache(\n\u001B[1;32m    634\u001B[0m                 m,\n\u001B[1;32m    635\u001B[0m                 stop\u001B[38;5;241m=\u001B[39mstop,\n\u001B[1;32m    636\u001B[0m                 run_manager\u001B[38;5;241m=\u001B[39mrun_managers[i] \u001B[38;5;28;01mif\u001B[39;00m run_managers \u001B[38;5;28;01melse\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m    637\u001B[0m                 \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m    638\u001B[0m             )\n\u001B[1;32m    639\u001B[0m         )\n\u001B[1;32m    640\u001B[0m     \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mBaseException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[1;32m    641\u001B[0m         \u001B[38;5;28;01mif\u001B[39;00m run_managers:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_core/language_models/chat_models.py:851\u001B[0m, in \u001B[0;36mBaseChatModel._generate_with_cache\u001B[0;34m(self, messages, stop, run_manager, **kwargs)\u001B[0m\n\u001B[1;32m    849\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    850\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m inspect\u001B[38;5;241m.\u001B[39msignature(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate)\u001B[38;5;241m.\u001B[39mparameters\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrun_manager\u001B[39m\u001B[38;5;124m\"\u001B[39m):\n\u001B[0;32m--> 851\u001B[0m         result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate(\n\u001B[1;32m    852\u001B[0m             messages, stop\u001B[38;5;241m=\u001B[39mstop, run_manager\u001B[38;5;241m=\u001B[39mrun_manager, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs\n\u001B[1;32m    853\u001B[0m         )\n\u001B[1;32m    854\u001B[0m     \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    855\u001B[0m         result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_generate(messages, stop\u001B[38;5;241m=\u001B[39mstop, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langchain_openai/chat_models/base.py:705\u001B[0m, in \u001B[0;36mBaseChatOpenAI._generate\u001B[0;34m(self, messages, stop, run_manager, **kwargs)\u001B[0m\n\u001B[1;32m    703\u001B[0m     generation_info \u001B[38;5;241m=\u001B[39m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mheaders\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mdict\u001B[39m(raw_response\u001B[38;5;241m.\u001B[39mheaders)}\n\u001B[1;32m    704\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m--> 705\u001B[0m     response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mclient\u001B[38;5;241m.\u001B[39mcreate(\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mpayload)\n\u001B[1;32m    706\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_create_chat_result(response, generation_info)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_utils/_utils.py:274\u001B[0m, in \u001B[0;36mrequired_args.<locals>.inner.<locals>.wrapper\u001B[0;34m(*args, **kwargs)\u001B[0m\n\u001B[1;32m    272\u001B[0m             msg \u001B[38;5;241m=\u001B[39m \u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mMissing required argument: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mquote(missing[\u001B[38;5;241m0\u001B[39m])\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m    273\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mTypeError\u001B[39;00m(msg)\n\u001B[0;32m--> 274\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m func(\u001B[38;5;241m*\u001B[39margs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/resources/chat/completions.py:815\u001B[0m, in \u001B[0;36mCompletions.create\u001B[0;34m(self, messages, model, audio, frequency_penalty, function_call, functions, logit_bias, logprobs, max_completion_tokens, max_tokens, metadata, modalities, n, parallel_tool_calls, presence_penalty, response_format, seed, service_tier, stop, store, stream, stream_options, temperature, tool_choice, tools, top_logprobs, top_p, user, extra_headers, extra_query, extra_body, timeout)\u001B[0m\n\u001B[1;32m    775\u001B[0m \u001B[38;5;129m@required_args\u001B[39m([\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodel\u001B[39m\u001B[38;5;124m\"\u001B[39m], [\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodel\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstream\u001B[39m\u001B[38;5;124m\"\u001B[39m])\n\u001B[1;32m    776\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mcreate\u001B[39m(\n\u001B[1;32m    777\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m    812\u001B[0m     timeout: \u001B[38;5;28mfloat\u001B[39m \u001B[38;5;241m|\u001B[39m httpx\u001B[38;5;241m.\u001B[39mTimeout \u001B[38;5;241m|\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m \u001B[38;5;241m|\u001B[39m NotGiven \u001B[38;5;241m=\u001B[39m NOT_GIVEN,\n\u001B[1;32m    813\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m ChatCompletion \u001B[38;5;241m|\u001B[39m Stream[ChatCompletionChunk]:\n\u001B[1;32m    814\u001B[0m     validate_response_format(response_format)\n\u001B[0;32m--> 815\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_post(\n\u001B[1;32m    816\u001B[0m         \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m/chat/completions\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[1;32m    817\u001B[0m         body\u001B[38;5;241m=\u001B[39mmaybe_transform(\n\u001B[1;32m    818\u001B[0m             {\n\u001B[1;32m    819\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: messages,\n\u001B[1;32m    820\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodel\u001B[39m\u001B[38;5;124m\"\u001B[39m: model,\n\u001B[1;32m    821\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124maudio\u001B[39m\u001B[38;5;124m\"\u001B[39m: audio,\n\u001B[1;32m    822\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfrequency_penalty\u001B[39m\u001B[38;5;124m\"\u001B[39m: frequency_penalty,\n\u001B[1;32m    823\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfunction_call\u001B[39m\u001B[38;5;124m\"\u001B[39m: function_call,\n\u001B[1;32m    824\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfunctions\u001B[39m\u001B[38;5;124m\"\u001B[39m: functions,\n\u001B[1;32m    825\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mlogit_bias\u001B[39m\u001B[38;5;124m\"\u001B[39m: logit_bias,\n\u001B[1;32m    826\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mlogprobs\u001B[39m\u001B[38;5;124m\"\u001B[39m: logprobs,\n\u001B[1;32m    827\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmax_completion_tokens\u001B[39m\u001B[38;5;124m\"\u001B[39m: max_completion_tokens,\n\u001B[1;32m    828\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmax_tokens\u001B[39m\u001B[38;5;124m\"\u001B[39m: max_tokens,\n\u001B[1;32m    829\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmetadata\u001B[39m\u001B[38;5;124m\"\u001B[39m: metadata,\n\u001B[1;32m    830\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodalities\u001B[39m\u001B[38;5;124m\"\u001B[39m: modalities,\n\u001B[1;32m    831\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mn\u001B[39m\u001B[38;5;124m\"\u001B[39m: n,\n\u001B[1;32m    832\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mparallel_tool_calls\u001B[39m\u001B[38;5;124m\"\u001B[39m: parallel_tool_calls,\n\u001B[1;32m    833\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mpresence_penalty\u001B[39m\u001B[38;5;124m\"\u001B[39m: presence_penalty,\n\u001B[1;32m    834\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mresponse_format\u001B[39m\u001B[38;5;124m\"\u001B[39m: response_format,\n\u001B[1;32m    835\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mseed\u001B[39m\u001B[38;5;124m\"\u001B[39m: seed,\n\u001B[1;32m    836\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mservice_tier\u001B[39m\u001B[38;5;124m\"\u001B[39m: service_tier,\n\u001B[1;32m    837\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstop\u001B[39m\u001B[38;5;124m\"\u001B[39m: stop,\n\u001B[1;32m    838\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstore\u001B[39m\u001B[38;5;124m\"\u001B[39m: store,\n\u001B[1;32m    839\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstream\u001B[39m\u001B[38;5;124m\"\u001B[39m: stream,\n\u001B[1;32m    840\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstream_options\u001B[39m\u001B[38;5;124m\"\u001B[39m: stream_options,\n\u001B[1;32m    841\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtemperature\u001B[39m\u001B[38;5;124m\"\u001B[39m: temperature,\n\u001B[1;32m    842\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtool_choice\u001B[39m\u001B[38;5;124m\"\u001B[39m: tool_choice,\n\u001B[1;32m    843\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtools\u001B[39m\u001B[38;5;124m\"\u001B[39m: tools,\n\u001B[1;32m    844\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtop_logprobs\u001B[39m\u001B[38;5;124m\"\u001B[39m: top_logprobs,\n\u001B[1;32m    845\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtop_p\u001B[39m\u001B[38;5;124m\"\u001B[39m: top_p,\n\u001B[1;32m    846\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124muser\u001B[39m\u001B[38;5;124m\"\u001B[39m: user,\n\u001B[1;32m    847\u001B[0m             },\n\u001B[1;32m    848\u001B[0m             completion_create_params\u001B[38;5;241m.\u001B[39mCompletionCreateParams,\n\u001B[1;32m    849\u001B[0m         ),\n\u001B[1;32m    850\u001B[0m         options\u001B[38;5;241m=\u001B[39mmake_request_options(\n\u001B[1;32m    851\u001B[0m             extra_headers\u001B[38;5;241m=\u001B[39mextra_headers, extra_query\u001B[38;5;241m=\u001B[39mextra_query, extra_body\u001B[38;5;241m=\u001B[39mextra_body, timeout\u001B[38;5;241m=\u001B[39mtimeout\n\u001B[1;32m    852\u001B[0m         ),\n\u001B[1;32m    853\u001B[0m         cast_to\u001B[38;5;241m=\u001B[39mChatCompletion,\n\u001B[1;32m    854\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28;01mFalse\u001B[39;00m,\n\u001B[1;32m    855\u001B[0m         stream_cls\u001B[38;5;241m=\u001B[39mStream[ChatCompletionChunk],\n\u001B[1;32m    856\u001B[0m     )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1277\u001B[0m, in \u001B[0;36mSyncAPIClient.post\u001B[0;34m(self, path, cast_to, body, options, files, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1263\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mpost\u001B[39m(\n\u001B[1;32m   1264\u001B[0m     \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m   1265\u001B[0m     path: \u001B[38;5;28mstr\u001B[39m,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m   1272\u001B[0m     stream_cls: \u001B[38;5;28mtype\u001B[39m[_StreamT] \u001B[38;5;241m|\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1273\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m ResponseT \u001B[38;5;241m|\u001B[39m _StreamT:\n\u001B[1;32m   1274\u001B[0m     opts \u001B[38;5;241m=\u001B[39m FinalRequestOptions\u001B[38;5;241m.\u001B[39mconstruct(\n\u001B[1;32m   1275\u001B[0m         method\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mpost\u001B[39m\u001B[38;5;124m\"\u001B[39m, url\u001B[38;5;241m=\u001B[39mpath, json_data\u001B[38;5;241m=\u001B[39mbody, files\u001B[38;5;241m=\u001B[39mto_httpx_files(files), \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39moptions\n\u001B[1;32m   1276\u001B[0m     )\n\u001B[0;32m-> 1277\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m cast(ResponseT, \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrequest(cast_to, opts, stream\u001B[38;5;241m=\u001B[39mstream, stream_cls\u001B[38;5;241m=\u001B[39mstream_cls))\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:954\u001B[0m, in \u001B[0;36mSyncAPIClient.request\u001B[0;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001B[0m\n\u001B[1;32m    951\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    952\u001B[0m     retries_taken \u001B[38;5;241m=\u001B[39m \u001B[38;5;241m0\u001B[39m\n\u001B[0;32m--> 954\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_request(\n\u001B[1;32m    955\u001B[0m     cast_to\u001B[38;5;241m=\u001B[39mcast_to,\n\u001B[1;32m    956\u001B[0m     options\u001B[38;5;241m=\u001B[39moptions,\n\u001B[1;32m    957\u001B[0m     stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m    958\u001B[0m     stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m    959\u001B[0m     retries_taken\u001B[38;5;241m=\u001B[39mretries_taken,\n\u001B[1;32m    960\u001B[0m )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1014\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1011\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mEncountered Exception\u001B[39m\u001B[38;5;124m\"\u001B[39m, exc_info\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m)\n\u001B[1;32m   1013\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m remaining_retries \u001B[38;5;241m>\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m-> 1014\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_retry_request(\n\u001B[1;32m   1015\u001B[0m         input_options,\n\u001B[1;32m   1016\u001B[0m         cast_to,\n\u001B[1;32m   1017\u001B[0m         retries_taken\u001B[38;5;241m=\u001B[39mretries_taken,\n\u001B[1;32m   1018\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1019\u001B[0m         stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1020\u001B[0m         response_headers\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1021\u001B[0m     )\n\u001B[1;32m   1023\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mRaising connection error\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m   1024\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m APIConnectionError(request\u001B[38;5;241m=\u001B[39mrequest) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01merr\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1092\u001B[0m, in \u001B[0;36mSyncAPIClient._retry_request\u001B[0;34m(self, options, cast_to, retries_taken, response_headers, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1088\u001B[0m \u001B[38;5;66;03m# In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a\u001B[39;00m\n\u001B[1;32m   1089\u001B[0m \u001B[38;5;66;03m# different thread if necessary.\u001B[39;00m\n\u001B[1;32m   1090\u001B[0m time\u001B[38;5;241m.\u001B[39msleep(timeout)\n\u001B[0;32m-> 1092\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_request(\n\u001B[1;32m   1093\u001B[0m     options\u001B[38;5;241m=\u001B[39moptions,\n\u001B[1;32m   1094\u001B[0m     cast_to\u001B[38;5;241m=\u001B[39mcast_to,\n\u001B[1;32m   1095\u001B[0m     retries_taken\u001B[38;5;241m=\u001B[39mretries_taken \u001B[38;5;241m+\u001B[39m \u001B[38;5;241m1\u001B[39m,\n\u001B[1;32m   1096\u001B[0m     stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1097\u001B[0m     stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1098\u001B[0m )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1014\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1011\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mEncountered Exception\u001B[39m\u001B[38;5;124m\"\u001B[39m, exc_info\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m)\n\u001B[1;32m   1013\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m remaining_retries \u001B[38;5;241m>\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m-> 1014\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_retry_request(\n\u001B[1;32m   1015\u001B[0m         input_options,\n\u001B[1;32m   1016\u001B[0m         cast_to,\n\u001B[1;32m   1017\u001B[0m         retries_taken\u001B[38;5;241m=\u001B[39mretries_taken,\n\u001B[1;32m   1018\u001B[0m         stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1019\u001B[0m         stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1020\u001B[0m         response_headers\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1021\u001B[0m     )\n\u001B[1;32m   1023\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mRaising connection error\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m   1024\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m APIConnectionError(request\u001B[38;5;241m=\u001B[39mrequest) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01merr\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1092\u001B[0m, in \u001B[0;36mSyncAPIClient._retry_request\u001B[0;34m(self, options, cast_to, retries_taken, response_headers, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1088\u001B[0m \u001B[38;5;66;03m# In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a\u001B[39;00m\n\u001B[1;32m   1089\u001B[0m \u001B[38;5;66;03m# different thread if necessary.\u001B[39;00m\n\u001B[1;32m   1090\u001B[0m time\u001B[38;5;241m.\u001B[39msleep(timeout)\n\u001B[0;32m-> 1092\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_request(\n\u001B[1;32m   1093\u001B[0m     options\u001B[38;5;241m=\u001B[39moptions,\n\u001B[1;32m   1094\u001B[0m     cast_to\u001B[38;5;241m=\u001B[39mcast_to,\n\u001B[1;32m   1095\u001B[0m     retries_taken\u001B[38;5;241m=\u001B[39mretries_taken \u001B[38;5;241m+\u001B[39m \u001B[38;5;241m1\u001B[39m,\n\u001B[1;32m   1096\u001B[0m     stream\u001B[38;5;241m=\u001B[39mstream,\n\u001B[1;32m   1097\u001B[0m     stream_cls\u001B[38;5;241m=\u001B[39mstream_cls,\n\u001B[1;32m   1098\u001B[0m )\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/openai/_base_client.py:1024\u001B[0m, in \u001B[0;36mSyncAPIClient._request\u001B[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001B[0m\n\u001B[1;32m   1014\u001B[0m         \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_retry_request(\n\u001B[1;32m   1015\u001B[0m             input_options,\n\u001B[1;32m   1016\u001B[0m             cast_to,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m   1020\u001B[0m             response_headers\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m   1021\u001B[0m         )\n\u001B[1;32m   1023\u001B[0m     log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mRaising connection error\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[0;32m-> 1024\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m APIConnectionError(request\u001B[38;5;241m=\u001B[39mrequest) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01merr\u001B[39;00m\n\u001B[1;32m   1026\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\n\u001B[1;32m   1027\u001B[0m     \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mHTTP Response: \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;132;01m%i\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m'\u001B[39m,\n\u001B[1;32m   1028\u001B[0m     request\u001B[38;5;241m.\u001B[39mmethod,\n\u001B[0;32m   (...)\u001B[0m\n\u001B[1;32m   1032\u001B[0m     response\u001B[38;5;241m.\u001B[39mheaders,\n\u001B[1;32m   1033\u001B[0m )\n\u001B[1;32m   1034\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrequest_id: \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m\"\u001B[39m, response\u001B[38;5;241m.\u001B[39mheaders\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mx-request-id\u001B[39m\u001B[38;5;124m\"\u001B[39m))\n",
      "\u001B[0;31mAPIConnectionError\u001B[0m: Connection error."
     ]
    }
   ],
   "source": [
    "from langchain_core.messages import BaseMessage\n",
    "\n",
    "# graph.invoke({\"messages\": [(\"user\", \"我需要10人生日是1970年之前的员工\")]})\n",
    "\n",
    "for event in graph.stream(\n",
    "    {\"messages\": [(\"user\", \"我需要2人生日是2000年之前的员工\")]}\n",
    "):\n",
    "    print(f\"Event:{event}\")\n",
    "    # if msg.content and isinstance(msg, AIMessage):\n",
    "    #     print(\"Assistant:\", msg.content)\n",
    "    # for value in event.values():\n",
    "    #         if isinstance(value[\"messages\"][-1], BaseMessage):\n",
    "    #             print(\"Assistant:\", value[\"messages\"][-1].content)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-22T09:14:33.050067Z",
     "start_time": "2024-11-22T09:13:23.882544Z"
    }
   },
   "id": "b458181c6323b79a",
   "execution_count": 419
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
